示例#1
0
int
probe_init(void)
{
	int scmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
	    CMSG_SPACE(sizeof(int));
	static u_char *sndcmsgbuf = NULL;

	if (sndcmsgbuf == NULL &&
	    (sndcmsgbuf = (u_char *)malloc(scmsglen)) == NULL) {
		warnmsg(LOG_ERR, __func__, "malloc failed");
		return (-1);
	}

	if ((probesock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
		return (-1);
	}

	/* make the socket send-only */
	if (shutdown(probesock, 0)) {
		warnmsg(LOG_ERR, __func__, "shutdown: %s", strerror(errno));
		return (-1);
	}

	/* initialize msghdr for sending packets */
	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
	sndmhdr.msg_iov = sndiov;
	sndmhdr.msg_iovlen = 1;
	sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
	sndmhdr.msg_controllen = scmsglen;

	return (0);
}
示例#2
0
/*
 * Probe if each router in the default router list is still alive.
 */
void
defrouter_probe(struct ifinfo *ifinfo)
{
	struct in6_defrouter *p, *ep;
	int ifindex, mib[4];
	char *buf, ntopbuf[INET6_ADDRSTRLEN];
	size_t l;

	ifindex = ifinfo->sdl->sdl_index;
	if (ifindex == 0)
		return;
	mib[0] = CTL_NET;
	mib[1] = PF_INET6;
	mib[2] = IPPROTO_ICMPV6;
	mib[3] = ICMPV6CTL_ND6_DRLIST;
	if (sysctl(mib, nitems(mib), NULL, &l, NULL, 0) < 0) {
		warnmsg(LOG_ERR, __func__, "sysctl(ICMPV6CTL_ND6_DRLIST): %s",
		    strerror(errno));
		return;
	}
	if (l == 0)
		return;
	buf = malloc(l);
	if (buf == NULL) {
		warnmsg(LOG_ERR, __func__, "malloc(): %s", strerror(errno));
		return;
	}
	if (sysctl(mib, nitems(mib), buf, &l, NULL, 0) < 0) {
		warnmsg(LOG_ERR, __func__, "sysctl(ICMPV6CTL_ND6_DRLIST): %s",
		    strerror(errno));
		free(buf);
		return;
	}
	ep = (struct in6_defrouter *)(void *)(buf + l);
	for (p = (struct in6_defrouter *)(void *)buf; p < ep; p++) {
		if (ifindex != p->if_index)
			continue;
		if (!IN6_IS_ADDR_LINKLOCAL(&p->rtaddr.sin6_addr)) {
			warnmsg(LOG_ERR, __func__,
			    "default router list contains a "
			    "non-link-local address(%s)",
			    inet_ntop(AF_INET6, &p->rtaddr.sin6_addr, ntopbuf,
			    INET6_ADDRSTRLEN));
			continue; /* ignore the address */
		}
		sendprobe(&p->rtaddr.sin6_addr, ifinfo);
	}
	free(buf);
}
示例#3
0
void
sendpacket(struct ifinfo *ifi)
{
	struct in6_pktinfo *pi;
	struct cmsghdr *cm;
	int hoplimit = 255;
	ssize_t i;
	struct sockaddr_in6 dst;

	dst = sin6_allrouters;
	dst.sin6_scope_id = ifi->linkid;

	sndmhdr.msg_name = (caddr_t)&dst;
	sndmhdr.msg_iov[0].iov_base = (caddr_t)ifi->rs_data;
	sndmhdr.msg_iov[0].iov_len = ifi->rs_datalen;

	cm = CMSG_FIRSTHDR(&sndmhdr);
	/* specify the outgoing interface */
	cm->cmsg_level = IPPROTO_IPV6;
	cm->cmsg_type = IPV6_PKTINFO;
	cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
	pi = (struct in6_pktinfo *)CMSG_DATA(cm);
	memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));	/*XXX*/
	pi->ipi6_ifindex = ifi->sdl->sdl_index;

	/* specify the hop limit of the packet */
	cm = CMSG_NXTHDR(&sndmhdr, cm);
	cm->cmsg_level = IPPROTO_IPV6;
	cm->cmsg_type = IPV6_HOPLIMIT;
	cm->cmsg_len = CMSG_LEN(sizeof(int));
	memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));

	warnmsg(LOG_DEBUG, __func__,
	    "send RS on %s, whose state is %d",
	    ifi->ifname, ifi->state);
	i = sendmsg(rssock, &sndmhdr, 0);
	if (i < 0 || (size_t)i != ifi->rs_datalen) {
		/*
		 * ENETDOWN is not so serious, especially when using several
		 * network cards on a mobile node. We ignore it.
		 */
		if (errno != ENETDOWN || dflag > 0)
			warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s",
			    ifi->ifname, strerror(errno));
	}

	/* update counter */
	ifi->probes++;
}
示例#4
0
FILE *faskwopen(char *query, char *filename, int opt) {

  char    ans;
  
  if (opt == 1 || opt == 2 || opt == 3) {

    if (opt == 1)
      get_input(query, "!%s", filename);
    else if (opt == 2)
      get_input(query, "%s", filename);

    while (!access(filename,W_OK) || filename[0] == '!') {
      if (filename[0] == '!')
	system(filename+1);
      else {
	warnmsg("File %s exists!", filename);
	ans = 'y';
	get_input("Overwrite (y/n)?", "%c", &ans);
	if (ans == 'y')
	  break;
      }
      get_input(query, "!%s", filename);
    }
  }
  else if (opt == 4)
    ;
  else if (opt == 5 && access(filename,W_OK))
    errormsg("faskwopen(): Cannot open file %s for writing",filename);
  else if (opt == 6)
    return fopen(filename, "a");
  else
    errormsg("faskwopen(): Unknown option: %d", opt);

  return fopen(filename, "w");
}
示例#5
0
文件: if.c 项目: AhmadTux/freebsd
/* get ia6_flags for link-local addr on if.  returns -1 on error. */
static int
get_llflag(const char *name)
{
	struct ifaddrs *ifap, *ifa;
	struct in6_ifreq ifr6;
	struct sockaddr_in6 *sin6;
	int s;

	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s",
		    strerror(errno));
		exit(1);
	}
	if (getifaddrs(&ifap) != 0) {
		warnmsg(LOG_ERR, __func__, "getifaddrs: %s",
		    strerror(errno));
		exit(1);
	}

	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
		if (strlen(ifa->ifa_name) != strlen(name) ||
		    strncmp(ifa->ifa_name, name, strlen(name)) != 0)
			continue;
		if (ifa->ifa_addr->sa_family != AF_INET6)
			continue;
		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
		if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
			continue;

		memset(&ifr6, 0, sizeof(ifr6));
		strncpy(ifr6.ifr_name, name, sizeof(ifr6.ifr_name));
		memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
		if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
			warnmsg(LOG_ERR, __func__,
			    "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
			exit(1);
		}

		freeifaddrs(ifap);
		close(s);
		return (ifr6.ifr_ifru.ifru_flags6);
	}

	freeifaddrs(ifap);
	close(s);
	return (-1);
}
示例#6
0
static void
sendprobe(struct in6_addr *addr, int ifindex)
{
	struct sockaddr_in6 sa6_probe;
	struct in6_pktinfo *pi;
	struct cmsghdr *cm;
	u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];;

	bzero(&sa6_probe, sizeof(sa6_probe));
	sa6_probe.sin6_family = AF_INET6;
	sa6_probe.sin6_len = sizeof(sa6_probe);
	sa6_probe.sin6_addr = *addr;

	sndmhdr.msg_name = (caddr_t)&sa6_probe;
	sndmhdr.msg_iov[0].iov_base = NULL;
	sndmhdr.msg_iov[0].iov_len = 0;

	cm = CMSG_FIRSTHDR(&sndmhdr);
	/* specify the outgoing interface */
	cm->cmsg_level = IPPROTO_IPV6;
	cm->cmsg_type = IPV6_PKTINFO;
	cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
	pi = (struct in6_pktinfo *)CMSG_DATA(cm);
	memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));	/*XXX*/
	pi->ipi6_ifindex = ifindex;

	/* specify the hop limit of the packet for safety */
	{
		int hoplimit = 1;

		cm = CMSG_NXTHDR(&sndmhdr, cm);
		cm->cmsg_level = IPPROTO_IPV6;
		cm->cmsg_type = IPV6_HOPLIMIT;
		cm->cmsg_len = CMSG_LEN(sizeof(int));
		memcpy(CMSG_DATA(cm), &hoplimit, sizeof(int));
	}

	warnmsg(LOG_DEBUG, __FUNCTION__, "probe a router %s on %s",
	       inet_ntop(AF_INET6, addr, (char *)ntopbuf, INET6_ADDRSTRLEN),
	       if_indextoname(ifindex, (char *)ifnamebuf));

	if (sendmsg(probesock, &sndmhdr, 0))
		warnmsg(LOG_ERR, __FUNCTION__, "sendmsg on %s: %s",
			if_indextoname(ifindex, (char *)ifnamebuf), strerror(errno));

	return;
}
示例#7
0
int
rtsock_input(int s)
{
	ssize_t n;
	char msg[2048];
	char *lim, *next;
	struct rt_msghdr *rtm;
	int idx;
	ssize_t len;
	int ret = 0;
	const ssize_t lenlim =
	    offsetof(struct rt_msghdr, rtm_msglen) + sizeof(rtm->rtm_msglen);

	n = read(s, msg, sizeof(msg));

	lim = msg + n;
	for (next = msg; next < lim; next += len) {
		rtm = (struct rt_msghdr *)(void *)next;
		if (lim - next < lenlim)
			break;
		len = rtm->rtm_msglen;
		if (len < lenlim)
			break;

		if (dflag > 1) {
			warnmsg(LOG_INFO, __func__,
			    "rtmsg type %d, len=%lu", rtm->rtm_type,
			    (u_long)len);
		}

		for (idx = 0; rtsock_dispatch[idx].func; idx++) {
			if (rtm->rtm_type != rtsock_dispatch[idx].type)
				continue;
			if (rtm->rtm_msglen < rtsock_dispatch[idx].minlen) {
				warnmsg(LOG_INFO, __func__,
				    "rtmsg type %d too short!", rtm->rtm_type);
				continue;
			}

			ret = (*rtsock_dispatch[idx].func)(s, rtm, lim);
			break;
		}
	}

	return (ret);
}
示例#8
0
int
shouldBan(struct boardheader *bh, int oldvalue)
{
	int limit, limit_new, count, fd = -1, ban = 0;
	char buf[256];
	time_t t = time(NULL);
	if (!oldvalue && !level)
		return oldvalue;
	limit = getlimit(bh);
	limit_new = limit + limit / 3;
	sprintf(buf, MY_BBS_HOME "/boards/%s/.DIR", bh->filename);
	count = file_size(buf) / sizeof (struct fileheader);

	if (count <= limit)
		return 0;
	if (count > limit_new + 500)
		goto SHOULDBAN;

	fd = open(buf, O_RDONLY);
	if (fd < 0)
		return 0;
	ban = max(ban, checklimit(fd, count, limit, 500, t - 3 * 24 * 3600));
	ban = max(ban, checklimit(fd, count, limit_new, 500, t - 12 * 3600));
	close(fd);

	if (ban == 2)
		goto SHOULDBAN;
	if (ban == 1)
		goto WOULDBAN;
	return 0;
      WOULDBAN:
	if (oldvalue != 1) {
		if (!level)
			return 0;
		warnmsg(bh, 1, limit, limit_new);
	}
	return 1;
      SHOULDBAN:
	if (oldvalue != 2) {
		if (level < 2)
			goto WOULDBAN;
		warnmsg(bh, 2, limit, limit_new);
	}
	return 2;
}
示例#9
0
文件: dump.c 项目: MarginC/kame
void
rtsold_dump_file(char *dumpfile)
{
	if ((fp = fopen(dumpfile, "w")) == NULL) {
		warnmsg(LOG_WARNING, __func__, "open a dump file(%s): %s",
		    dumpfile, strerror(errno));
		return;
	}
	dump_interface_status();
	fclose(fp);
}
示例#10
0
int
ifinit(void)
{
	cap_rights_t rights;
	int sock;

	sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
	if (sock < 0) {
		warnmsg(LOG_ERR, __func__, "socket(): %s",
		    strerror(errno));
		return (-1);
	}
	if (caph_rights_limit(sock, cap_rights_init(&rights, CAP_IOCTL)) < 0) {
		warnmsg(LOG_ERR, __func__, "caph_rights_limit(): %s",
		    strerror(errno));
		(void)close(sock);
		return (-1);
	}
	ifsock = sock;
	return (0);
}
示例#11
0
/*
 * Probe if each router in the default router list is still alive. 
 */
void
defrouter_probe(int ifindex)
{
	struct in6_drlist dr;
	int s, i;
	u_char ntopbuf[INET6_ADDRSTRLEN];

	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
		warnmsg(LOG_ERR, __FUNCTION__, "socket: %s", strerror(errno));
		return;
	}
	bzero(&dr, sizeof(dr));
	strlcpy(dr.ifname, "lo0", sizeof(dr.ifname)); /* dummy interface */
	if (ioctl(s, SIOCGDRLST_IN6, (caddr_t)&dr) < 0) {
		warnmsg(LOG_ERR, __FUNCTION__, "ioctl(SIOCGDRLST_IN6): %s",
		       strerror(errno));
		goto closeandend;
	}

	for(i = 0; dr.defrouter[i].if_index && i < PRLSTSIZ; i++) {
		if (ifindex && dr.defrouter[i].if_index == ifindex) {
			/* sanity check */
			if (!IN6_IS_ADDR_LINKLOCAL(&dr.defrouter[i].rtaddr)) {
				warnmsg(LOG_ERR, __FUNCTION__,
					"default router list contains a "
					"non-linklocal address(%s)",
				       inet_ntop(AF_INET6,
						 &dr.defrouter[i].rtaddr,
						 (char *)ntopbuf, INET6_ADDRSTRLEN));
				continue; /* ignore the address */
			}
			sendprobe(&dr.defrouter[i].rtaddr,
				  dr.defrouter[i].if_index);
		}
	}

  closeandend:
	close(s);
	return;
}
示例#12
0
/*
 * Copyright (C) 2000 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/param.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/queue.h>

#include <net/if.h>
#include <net/route.h>
#include <net/if_dl.h>

#include <netinet/in.h>
#include <netinet/ip6.h>
#include <netinet/icmp6.h>

#include <time.h>
#include <unistd.h>
#include <stdio.h>
#include <stddef.h>
#include <err.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <syslog.h>
#include "rtsold.h"

#define ROUNDUP(a, size) \
	(((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))

#define NEXT_SA(ap) (ap) = (struct sockaddr *) \
	((caddr_t)(ap) + \
	 ((ap)->sa_len ? ROUNDUP((ap)->sa_len, sizeof(u_long)) \
		       : sizeof(u_long)))

#ifdef RTM_IFANNOUNCE	/*NetBSD 1.5 or later*/
static int rtsock_input_ifannounce(int, struct rt_msghdr *, char *);
#endif

static struct {
	u_char type;
	size_t minlen;
	int (*func)(int, struct rt_msghdr *, char *);
} rtsock_dispatch[] = {
#ifdef RTM_IFANNOUNCE	/*NetBSD 1.5 or later*/
	{ RTM_IFANNOUNCE, sizeof(struct if_announcemsghdr),
	  rtsock_input_ifannounce },
#endif
	{ 0, 0, NULL },
};

int
rtsock_open(void)
{

	return (socket(PF_ROUTE, SOCK_RAW, 0));
}

int
rtsock_input(int s)
{
	ssize_t n;
	char msg[2048];
	char *lim, *next;
	struct rt_msghdr *rtm;
	int idx;
	ssize_t len;
	int ret = 0;
	const ssize_t lenlim =
	    offsetof(struct rt_msghdr, rtm_msglen) + sizeof(rtm->rtm_msglen);

	n = read(s, msg, sizeof(msg));

	lim = msg + n;
	for (next = msg; next < lim; next += len) {
		rtm = (struct rt_msghdr *)(void *)next;
		if (lim - next < lenlim)
			break;
		len = rtm->rtm_msglen;
		if (len < lenlim)
			break;

		if (dflag > 1) {
			warnmsg(LOG_INFO, __func__,
			    "rtmsg type %d, len=%lu", rtm->rtm_type,
			    (u_long)len);
		}

		for (idx = 0; rtsock_dispatch[idx].func; idx++) {
			if (rtm->rtm_type != rtsock_dispatch[idx].type)
				continue;
			if (rtm->rtm_msglen < rtsock_dispatch[idx].minlen) {
				warnmsg(LOG_INFO, __func__,
				    "rtmsg type %d too short!", rtm->rtm_type);
				continue;
			}

			ret = (*rtsock_dispatch[idx].func)(s, rtm, lim);
			break;
		}
	}

	return (ret);
}

#ifdef RTM_IFANNOUNCE	/*NetBSD 1.5 or later*/
static int
rtsock_input_ifannounce(int s __unused, struct rt_msghdr *rtm, char *lim)
{
	struct if_announcemsghdr *ifan;
	struct ifinfo *ifi;

	ifan = (struct if_announcemsghdr *)rtm;
	if ((char *)(ifan + 1) > lim)
		return (-1);

	switch (ifan->ifan_what) {
	case IFAN_ARRIVAL:
		/*
		 * XXX for NetBSD 1.5, interface index will monotonically be
		 * increased as new pcmcia card gets inserted.
		 * we may be able to do a name-based interface match,
		 * and call ifreconfig() to enable the interface again.
		 */
		warnmsg(LOG_INFO, __func__,
		    "interface %s inserted", ifan->ifan_name);
		break;
	case IFAN_DEPARTURE:
		warnmsg(LOG_WARNING, __func__,
		    "interface %s removed", ifan->ifan_name);
		ifi = find_ifinfo(ifan->ifan_index);
		if (ifi) {
			if (dflag > 1) {
				warnmsg(LOG_INFO, __func__,
				    "bring interface %s to DOWN state",
				    ifan->ifan_name);
			}
			ifi->state = IFS_DOWN;
		}
		break;
	}

	return (0);
}
示例#13
0
static int
make_packet(struct ifinfo *ifinfo)
{
	char *buf;
	struct nd_router_solicit *rs;
	size_t packlen = sizeof(struct nd_router_solicit), lladdroptlen = 0;

	if ((lladdroptlen = lladdropt_length(ifinfo->sdl)) == 0) {
		warnmsg(LOG_INFO, __func__,
			"link-layer address option has null length"
		       " on %s. Treat as not included.", ifinfo->ifname);
	}
	packlen += lladdroptlen;
	ifinfo->rs_datalen = packlen;

	/* allocate buffer */
	if ((buf = malloc(packlen)) == NULL) {
		warnmsg(LOG_ERR, __func__,
			"memory allocation failed for %s", ifinfo->ifname);
		return(-1);
	}
	ifinfo->rs_data = buf;

	/* fill in the message */
	rs = (struct nd_router_solicit *)buf;
	rs->nd_rs_type = ND_ROUTER_SOLICIT;
	rs->nd_rs_code = 0;
	rs->nd_rs_cksum = 0;
	rs->nd_rs_reserved = 0;
	buf += sizeof(*rs);

	/* fill in source link-layer address option */
	if (lladdroptlen)
		lladdropt_fill(ifinfo->sdl, (struct nd_opt_hdr *)buf);

	return(0);
}
示例#14
0
文件: if.c 项目: kusumi/DragonFlyBSD
int
interface_up(char *name)
{
	struct ifreq ifr;
	int llflag;

	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));

	if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
		warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s",
		       strerror(errno));
		return(-1);
	}
	if (!(ifr.ifr_flags & IFF_UP)) {
		ifr.ifr_flags |= IFF_UP;
		if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
			warnmsg(LOG_ERR, __func__,
				"ioctl(SIOCSIFFLAGS): %s", strerror(errno));
		}
		return(-1);
	}

	warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name);

	llflag = get_llflag(name);
	if (llflag < 0) {
		warnmsg(LOG_WARNING, __func__,
			"get_llflag() failed, anyway I'll try");
		return 0;
	}

	if (!(llflag & IN6_IFF_NOTREADY)) {
		warnmsg(LOG_DEBUG, __func__,
			"%s is ready", name);
		return(0);
	} else {
		if (llflag & IN6_IFF_TENTATIVE) {
			warnmsg(LOG_DEBUG, __func__, "%s is tentative",
			       name);
			return IFS_TENTATIVE;
		}
		if (llflag & IN6_IFF_DUPLICATED)
			warnmsg(LOG_DEBUG, __func__, "%s is duplicated",
			       name);
		return -1;
	}
}
示例#15
0
void
lladdropt_fill(struct sockaddr_dl *sdl, struct nd_opt_hdr *ndopt)
{
	char *addr;

	ndopt->nd_opt_type = ND_OPT_SOURCE_LINKADDR; /* fixed */

	switch (sdl->sdl_type) {
	case IFT_ETHER:
		ndopt->nd_opt_len = (ROUNDUP8(ETHER_ADDR_LEN + 2)) >> 3;
		addr = (char *)(ndopt + 1);
		memcpy(addr, LLADDR(sdl), ETHER_ADDR_LEN);
		break;
	default:
		warnmsg(LOG_ERR, __func__,
		    "unsupported link type(%d)", sdl->sdl_type);
		exit(1);
	}
}
示例#16
0
文件: if.c 项目: AhmadTux/freebsd
int
interface_up(char *name)
{
	struct ifreq ifr;
	struct in6_ndireq nd;
	int llflag;
	int s;

	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
	memset(&nd, 0, sizeof(nd));
	strlcpy(nd.ifname, name, sizeof(nd.ifname));

	if (ioctl(ifsock, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
		warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFFLAGS): %s",
		    strerror(errno));
		return (-1);
	}
	if (!(ifr.ifr_flags & IFF_UP)) {
		ifr.ifr_flags |= IFF_UP;
		if (ioctl(ifsock, SIOCSIFFLAGS, (caddr_t)&ifr) < 0)
			warnmsg(LOG_ERR, __func__,
			    "ioctl(SIOCSIFFLAGS): %s", strerror(errno));
		return (-1);
	}
	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
		warnmsg(LOG_WARNING, __func__, "socket(AF_INET6, SOCK_DGRAM): %s",
		    strerror(errno));
		return (-1);
	}
	if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
		warnmsg(LOG_WARNING, __func__, "ioctl(SIOCGIFINFO_IN6): %s",
		    strerror(errno));
		close(s);
		return (-1);
	}

	warnmsg(LOG_DEBUG, __func__, "checking if %s is ready...", name);

	if (nd.ndi.flags & ND6_IFF_IFDISABLED) {
		if (Fflag) {
			nd.ndi.flags &= ~ND6_IFF_IFDISABLED;
			if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) {
				warnmsg(LOG_WARNING, __func__,
				    "ioctl(SIOCSIFINFO_IN6): %s",
		    		    strerror(errno));
				close(s);
				return (-1);
			}
		} else {
			warnmsg(LOG_WARNING, __func__,
			    "%s is disabled.", name);
			close(s);
			return (-1);
		}
	}
	if (!(nd.ndi.flags & ND6_IFF_ACCEPT_RTADV)) {
		if (Fflag) {
			nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV;
			if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd)) {
				warnmsg(LOG_WARNING, __func__,
				    "ioctl(SIOCSIFINFO_IN6): %s",
		    		    strerror(errno));
				close(s);
				return (-1);
			}
		} else {
			warnmsg(LOG_WARNING, __func__,
			    "%s does not accept Router Advertisement.", name);
			close(s);
			return (-1);
		}
	}
	close(s);

	llflag = get_llflag(name);
	if (llflag < 0) {
		warnmsg(LOG_WARNING, __func__,
		    "get_llflag() failed, anyway I'll try");
		return (0);
	}

	if (!(llflag & IN6_IFF_NOTREADY)) {
		warnmsg(LOG_DEBUG, __func__, "%s is ready", name);
		return (0);
	} else {
		if (llflag & IN6_IFF_TENTATIVE) {
			warnmsg(LOG_DEBUG, __func__, "%s is tentative",
			    name);
			return (IFS_TENTATIVE);
		}
		if (llflag & IN6_IFF_DUPLICATED)
			warnmsg(LOG_DEBUG, __func__, "%s is duplicated",
			    name);
		return (-1);
	}
}
示例#17
0
文件: if.c 项目: AhmadTux/freebsd
int
interface_status(struct ifinfo *ifinfo)
{
	char *ifname = ifinfo->ifname;
	struct ifreq ifr;
	struct ifmediareq ifmr;

	/* get interface flags */
	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
	if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
		warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFFLAGS) on %s: %s",
		    ifname, strerror(errno));
		return (-1);
	}
	/*
	 * if one of UP and RUNNING flags is dropped,
	 * the interface is not active.
	 */
	if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
		goto inactive;
	/* Next, check carrier on the interface, if possible */
	if (!ifinfo->mediareqok)
		goto active;
	memset(&ifmr, 0, sizeof(ifmr));
	strncpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));

	if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
		if (errno != EINVAL) {
			warnmsg(LOG_DEBUG, __func__,
			    "ioctl(SIOCGIFMEDIA) on %s: %s",
			    ifname, strerror(errno));
			return(-1);
		}
		/*
		 * EINVAL simply means that the interface does not support
		 * the SIOCGIFMEDIA ioctl. We regard it alive.
		 */
		ifinfo->mediareqok = 0;
		goto active;
	}

	if (ifmr.ifm_status & IFM_AVALID) {
		switch (ifmr.ifm_active & IFM_NMASK) {
		case IFM_ETHER:
		case IFM_IEEE80211:
			if (ifmr.ifm_status & IFM_ACTIVE)
				goto active;
			else
				goto inactive;
			break;
		default:
			goto inactive;
		}
	}

  inactive:
	return (0);

  active:
	return (1);
}
示例#18
0
文件: ubiformat.c 项目: OPSF/uClinux
int main(int argc, char * const argv[])
{
	int err, verbose;
	libmtd_t libmtd;
	struct mtd_info mtd_info;
	struct mtd_dev_info mtd;
	libubi_t libubi;
	struct ubigen_info ui;
	struct ubi_scan_info *si;

	libmtd = libmtd_open();
	if (!libmtd)
		return errmsg("MTD subsystem is not present");

	err = parse_opt(argc, argv);
	if (err)
		goto out_close_mtd;

	err = mtd_get_info(libmtd, &mtd_info);
	if (err) {
		if (errno == ENODEV)
			errmsg("MTD is not present");
		sys_errmsg("cannot get MTD information");
		goto out_close_mtd;
	}

	err = mtd_get_dev_info(libmtd, args.node, &mtd);
	if (err) {
		sys_errmsg("cannot get information about \"%s\"", args.node);
		goto out_close_mtd;
	}

	if (!is_power_of_2(mtd.min_io_size)) {
		errmsg("min. I/O size is %d, but should be power of 2",
		       mtd.min_io_size);
		goto out_close;
	}

	if (!mtd_info.sysfs_supported) {
		/*
		 * Linux kernels older than 2.6.30 did not support sysfs
		 * interface, and it is impossible to find out sub-page
		 * size in these kernels. This is why users should
		 * provide -s option.
		 */
		if (args.subpage_size == 0) {
			warnmsg("your MTD system is old and it is impossible "
				"to detect sub-page size. Use -s to get rid "
				"of this warning");
			normsg("assume sub-page to be %d", mtd.subpage_size);
		} else {
			mtd.subpage_size = args.subpage_size;
			args.manual_subpage = 1;
		}
	} else if (args.subpage_size && args.subpage_size != mtd.subpage_size) {
		mtd.subpage_size = args.subpage_size;
		args.manual_subpage = 1;
	}

	if (args.manual_subpage) {
		/* Do some sanity check */
		if (args.subpage_size > mtd.min_io_size) {
			errmsg("sub-page cannot be larger than min. I/O unit");
			goto out_close;
		}

		if (mtd.min_io_size % args.subpage_size) {
			errmsg("min. I/O unit size should be multiple of "
			       "sub-page size");
			goto out_close;
		}
	}

	args.node_fd = open(args.node, O_RDWR);
	if (args.node_fd == -1) {
		sys_errmsg("cannot open \"%s\"", args.node);
		goto out_close_mtd;
	}

	/* Validate VID header offset if it was specified */
	if (args.vid_hdr_offs != 0) {
		if (args.vid_hdr_offs % 8) {
			errmsg("VID header offset has to be multiple of min. I/O unit size");
			goto out_close;
		}
		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) {
			errmsg("bad VID header offset");
			goto out_close;
		}
	}

	if (!mtd.writable) {
		errmsg("mtd%d (%s) is a read-only device", mtd.mtd_num, args.node);
		goto out_close;
	}

	/* Make sure this MTD device is not attached to UBI */
	libubi = libubi_open();
	if (libubi) {
		int ubi_dev_num;

		err = mtd_num2ubi_dev(libubi, mtd.mtd_num, &ubi_dev_num);
		libubi_close(libubi);
		if (!err) {
			errmsg("please, first detach mtd%d (%s) from ubi%d",
			       mtd.mtd_num, args.node, ubi_dev_num);
			goto out_close;
		}
	}

	if (!args.quiet) {
		normsg_cont("mtd%d (%s), size ", mtd.mtd_num, mtd.type_str);
		ubiutils_print_bytes(mtd.size, 1);
		printf(", %d eraseblocks of ", mtd.eb_cnt);
		ubiutils_print_bytes(mtd.eb_size, 1);
		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
	}

	if (args.quiet)
		verbose = 0;
	else if (args.verbose)
		verbose = 2;
	else
		verbose = 1;
	err = ubi_scan(&mtd, args.node_fd, &si, verbose);
	if (err) {
		errmsg("failed to scan mtd%d (%s)", mtd.mtd_num, args.node);
		goto out_close;
	}

	if (si->good_cnt == 0) {
		errmsg("all %d eraseblocks are bad", si->bad_cnt);
		goto out_free;
	}

	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
		errmsg("too few non-bad eraseblocks (%d) on mtd%d",
		       si->good_cnt, mtd.mtd_num);
		goto out_free;
	}

	if (!args.quiet) {
		if (si->ok_cnt)
			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
			       si->ok_cnt, si->mean_ec);
		if (si->empty_cnt)
			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
		if (si->corrupted_cnt)
			normsg("%d corrupted erase counters", si->corrupted_cnt);
		print_bad_eraseblocks(&mtd, si);
	}

	if (si->alien_cnt) {
		if (!args.yes || !args.quiet)
			warnmsg("%d of %d eraseblocks contain non-ubifs data",
				si->alien_cnt, si->good_cnt);
		if (!args.yes && want_exit()) {
			if (args.yes && !args.quiet)
				printf("yes\n");
			goto out_free;
		}
	}

	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
		int percent = ((double)si->ok_cnt)/si->good_cnt * 100;

		/*
		 * Make sure the majority of eraseblocks have valid
		 * erase counters.
		 */
		if (percent < 50) {
			if (!args.yes || !args.quiet)
				warnmsg("only %d of %d eraseblocks have valid erase counter",
					si->ok_cnt, si->good_cnt);
				normsg("erase counter 0 will be used for all eraseblocks");
				normsg("note, arbitrary erase counter value may be specified using -e option");
			if (!args.yes && want_exit()) {
				if (args.yes && !args.quiet)
					printf("yes\n");
				goto out_free;
			}
			 args.ec = 0;
			 args.override_ec = 1;
		} else if (percent < 95) {
			if (!args.yes || !args.quiet)
				warnmsg("only %d of %d eraseblocks have valid erase counter",
					si->ok_cnt, si->good_cnt);
				normsg("mean erase counter %lld will be used for the rest of eraseblock",
				       si->mean_ec);
			if (!args.yes && want_exit()) {
				if (args.yes && !args.quiet)
					printf("yes\n");
				goto out_free;
			}
			args.ec = si->mean_ec;
			args.override_ec = 1;
		}
	}

	if (!args.quiet && args.override_ec)
		normsg("use erase counter %lld for all eraseblocks", args.ec);

	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, mtd.subpage_size,
			 args.vid_hdr_offs, args.ubi_ver, args.image_seq);

	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
		/*
		 * Hmm, what we read from flash and what we calculated using
		 * min. I/O unit size and sub-page size differs.
		 */
		if (!args.yes || !args.quiet) {
			warnmsg("VID header and data offsets on flash are %d and %d, "
				"which is different to requested offsets %d and %d",
				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
				ui.data_offs);
			normsg_cont("use new offsets %d and %d? (yes/no)  ",
				    ui.vid_hdr_offs, ui.data_offs);
		}
		if (args.yes || answer_is_yes()) {
			if (args.yes && !args.quiet)
				printf("yes\n");
		} else
			ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, 0,
					 si->vid_hdr_offs, args.ubi_ver,
					 args.image_seq);
		normsg("use offsets %d and %d",  ui.vid_hdr_offs, ui.data_offs);
	}

	if (args.image) {
		err = flash_image(libmtd, &mtd, &ui, si);
		if (err < 0)
			goto out_free;

		err = format(libmtd, &mtd, &ui, si, err, 1);
		if (err)
			goto out_free;
	} else {
		err = format(libmtd, &mtd, &ui, si, 0, args.novtbl);
		if (err)
			goto out_free;
	}

	ubi_scan_free(si);
	close(args.node_fd);
	libmtd_close(libmtd);
	return 0;

out_free:
	ubi_scan_free(si);
out_close:
	close(args.node_fd);
out_close_mtd:
	libmtd_close(libmtd);
	return -1;
}
示例#19
0
int svdfit(double *x, double *y, double *sig, int ndata, double *a, int ma,
	double ***u, double ***v, double **w, double *chisq,
	int (*funcs)(double, double *, int)) {

  int     i=0,j=0;
  double  wmax=0.0,tmp=0.0,thresh=0.0,sum=0.0;
  double  *b=NULL,*afunc=NULL;

  /* Allocate memory for relevant arrays/matrices */
  if ((b=darray(ndata))==NULL) {
    nferrormsg("svdfit(): Cannot allocate memory to b\n\tarray of size %d",
	       ndata); return 0;
  }
  if ((afunc=darray(ma))==NULL) {
    nferrormsg("svdfit(): Cannot allocate memory to afunc\n\tarray of size %d",
	       ma); return 0;
  }
  if ((*w=darray(ma))==NULL) {
    nferrormsg("svdfit(): Cannot allocate memory to w\n\tarray of size %d",
	       ma); return 0;
  }
  if ((*u=dmatrix(ndata,ma))==NULL) {
    nferrormsg("svdfit(): Cannot allocate memory to matrix\n\t of size %dx%d",
	       ndata,ma); return 0;
  }
  if ((*v=dmatrix(ma,ma))==NULL) {
    nferrormsg("svdfit(): Cannot allocate memory to matrix\n\t of size %dx%d",
	       ma,ma); return 0;
  }

  /* Begin SVD fitting */
  for (i=0; i<ndata; i++) {
    if (!(*funcs)(x[i],afunc,ma)) {
      nferrormsg("svdfit(): Error returned from fitting function");
      return 0;
    }
    tmp=1.0/sig[i];
    for (j=0; j<ma; j++) (*u)[i][j]=afunc[j]*tmp;
    b[i]=y[i]*tmp;
  }
  if (!svdcmp(*u,ndata,ma,*w,*v)) {
    nferrormsg("svdfit(): Error returned from svdcmp()"); return 0;
  }
  wmax=0.0; for (j=0; j<ma; j++) wmax=MAX(wmax,(*w)[j]); thresh=SVDFIT_TOL*wmax;
  for (j=0; j<ma; j++) {
    if ((*w)[j]<thresh) {
      (*w)[j]=0.0;
      warnmsg("svdfit(): Setting coefficient %d's singular value to zero",j);
    }
  }
  if (!svbksb(*u,*w,*v,ndata,ma,b,a)) {
    nferrormsg("svdfit(): Error returned from svbksb()"); return 0;
  }
  *chisq=0.0;
  for (i=0; i<ndata; i++) {
    if (!(*funcs)(x[i],afunc,ma)) {
      nferrormsg("svdfit(): Error returned from fitting function");
      return 0;
    }
    for (sum=0.0,j=0; j<ma; j++) sum+=a[j]*afunc[j];
    *chisq+=(tmp=(y[i]-sum)/sig[i],tmp*tmp);
  }

  /* Clean up */
  free(b);
  free(afunc);

  return 1;

}
示例#20
0
文件: if.c 项目: kusumi/DragonFlyBSD
/* get ia6_flags for link-local addr on if.  returns -1 on error. */
static int
get_llflag(const char *name)
{
#ifdef HAVE_GETIFADDRS
	struct ifaddrs *ifap, *ifa;
	struct in6_ifreq ifr6;
	struct sockaddr_in6 *sin6;
	int s;

	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s",
		    strerror(errno));
		exit(1);
	}
	if (getifaddrs(&ifap) != 0) {
		warnmsg(LOG_ERR, __func__, "etifaddrs: %s",
		    strerror(errno));
		exit(1);
	}

	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
		if (strlen(ifa->ifa_name) != strlen(name)
		 || strncmp(ifa->ifa_name, name, strlen(name)) != 0)
			continue;
		if (ifa->ifa_addr->sa_family != AF_INET6)
			continue;
		sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
		if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
			continue;

		memset(&ifr6, 0, sizeof(ifr6));
		strcpy(ifr6.ifr_name, name);
		memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
		if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
			warnmsg(LOG_ERR, __func__,
			    "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
			exit(1);
		}

		freeifaddrs(ifap);
		close(s);
		return ifr6.ifr_ifru.ifru_flags6;
	}

	freeifaddrs(ifap);
	close(s);
	return -1;
#else
	int s;
	unsigned int maxif;
	struct ifreq *iflist;
	struct ifconf ifconf;
	struct ifreq *ifr, *ifr_end;
	struct sockaddr_in6 *sin6;
	struct in6_ifreq ifr6;

	maxif = if_maxindex() + 1;
	iflist = (struct ifreq *)malloc(maxif * BUFSIZ);	/* XXX */
	if (iflist == NULL) {
		warnmsg(LOG_ERR, __func__, "not enough core");
		exit(1);
	}

	if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket(SOCK_DGRAM): %s",
		    strerror(errno));
		exit(1);
	}
	memset(&ifconf, 0, sizeof(ifconf));
	ifconf.ifc_req = iflist;
	ifconf.ifc_len = maxif * BUFSIZ;	/* XXX */
	if (ioctl(s, SIOCGIFCONF, &ifconf) < 0) {
		warnmsg(LOG_ERR, __func__, "ioctl(SIOCGIFCONF): %s",
		    strerror(errno));
		exit(1);
	}

	/* Look for this interface in the list */
	ifr_end = (struct ifreq *) (ifconf.ifc_buf + ifconf.ifc_len);
	for (ifr = ifconf.ifc_req;
	     ifr < ifr_end;
	     ifr = (struct ifreq *) ((char *) &ifr->ifr_addr
				    + ifr->ifr_addr.sa_len)) {
		if (strlen(ifr->ifr_name) != strlen(name)
		 || strncmp(ifr->ifr_name, name, strlen(name)) != 0)
			continue;
		if (ifr->ifr_addr.sa_family != AF_INET6)
			continue;
		sin6 = (struct sockaddr_in6 *)&ifr->ifr_addr;
		if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
			continue;

		memset(&ifr6, 0, sizeof(ifr6));
		strcpy(ifr6.ifr_name, name);
		memcpy(&ifr6.ifr_ifru.ifru_addr, sin6, sin6->sin6_len);
		if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
			warnmsg(LOG_ERR, __func__,
			    "ioctl(SIOCGIFAFLAG_IN6): %s", strerror(errno));
			exit(1);
		}

		free(iflist);
		close(s);
		return ifr6.ifr_ifru.ifru_flags6;
	}

	free(iflist);
	close(s);
	return -1;
#endif
}
示例#21
0
void printdir(char *o, size_t size, struct dir *d, const char *path, int recurse,
		int want_ctime)
{
	char m;
	char *filetime;
	time_t age;
	struct jffs2_raw_inode *ri;
	jint32_t mode;

	if (!path)
		return;
	if (strlen(path) == 1 && *path == '/')
		path++;

	while (d != NULL) {
		switch (d->type) {
			case DT_REG:
				m = ' ';
				break;

			case DT_FIFO:
				m = '|';
				break;

			case DT_CHR:
				m = ' ';
				break;

			case DT_BLK:
				m = ' ';
				break;

			case DT_DIR:
				m = '/';
				break;

			case DT_LNK:
				m = ' ';
				break;

			case DT_SOCK:
				m = '=';
				break;

			default:
				m = '?';
		}
		ri = find_raw_inode(o, size, d->ino);
		if (!ri) {
			warnmsg("bug: raw_inode missing!");
			d = d->next;
			continue;
		}

		filetime = ctime((const time_t *) &(ri->ctime));
		age = time(NULL) - je32_to_cpu(ri->ctime);
		mode.v32 = ri->mode.m;
		printf("%s %-4d %-8d %-8d ", mode_string(je32_to_cpu(mode)),
				1, je16_to_cpu(ri->uid), je16_to_cpu(ri->gid));
		if ( d->type==DT_BLK || d->type==DT_CHR ) {
			dev_t rdev;
			size_t devsize;
			putblock((char*)&rdev, sizeof(rdev), &devsize, ri);
			printf("%4d, %3d ", major(rdev), minor(rdev));
		} else {
			printf("%9ld ", (long)je32_to_cpu(ri->dsize));
		}
		d->name[d->nsize]='\0';
		if (want_ctime) {
			if (age < 3600L * 24 * 365 / 2 && age > -15 * 60)
				/* hh:mm if less than 6 months old */
				printf("%6.6s %5.5s ", filetime + 4, filetime + 11);
			else
				printf("%6.6s %4.4s ", filetime + 4, filetime + 20);
		}
		printf("%s/%s%c", path, d->name, m);
		if (d->type == DT_LNK) {
			char symbuf[1024];
			size_t symsize;
			putblock(symbuf, sizeof(symbuf), &symsize, ri);
			symbuf[symsize] = 0;
			printf(" -> %s", symbuf);
		}
		printf("\n");

		if (d->type == DT_DIR && recurse) {
			char *tmp;
			tmp = xmalloc(BUFSIZ);
			sprintf(tmp, "%s/%s", path, d->name);
			lsdir(o, size, tmp, recurse, want_ctime);	/* Go recursive */
			free(tmp);
		}

		d = d->next;
	}
}
示例#22
0
int do_ubiformat(int argc, char *argv[])
{
	int err, verbose;
	struct mtd_dev_info mtd;
	struct ubigen_info ui;
	struct ubi_scan_info *si;

	err = parse_opt(argc, argv);
	if (err)
		return err;

	err = mtd_get_dev_info(args.node, &mtd);
	if (err) {
		sys_errmsg("cannot get information about \"%s\"", args.node);
		goto out_close_mtd;
	}

	if (!is_power_of_2(mtd.min_io_size)) {
		errmsg("min. I/O size is %d, but should be power of 2",
		       mtd.min_io_size);
		goto out_close_mtd;
	}

	if (args.subpage_size && args.subpage_size != mtd.subpage_size) {
		mtd.subpage_size = args.subpage_size;
		args.manual_subpage = 1;
	}

	if (args.manual_subpage) {
		/* Do some sanity check */
		if (args.subpage_size > mtd.min_io_size) {
			errmsg("sub-page cannot be larger than min. I/O unit");
			goto out_close_mtd;
		}

		if (mtd.min_io_size % args.subpage_size) {
			errmsg("min. I/O unit size should be multiple of "
			       "sub-page size");
			goto out_close_mtd;
		}
	}

	args.node_fd = open(args.node, O_RDWR);
	if (args.node_fd < 0) {
		sys_errmsg("cannot open \"%s\"", args.node);
		goto out_close_mtd;
	}

	/* Validate VID header offset if it was specified */
	if (args.vid_hdr_offs != 0) {
		if (args.vid_hdr_offs % 8) {
			errmsg("VID header offset has to be multiple of min. I/O unit size");
			goto out_close;
		}
		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) {
			errmsg("bad VID header offset");
			goto out_close;
		}
	}

	if (!mtd.writable) {
		errmsg("%s (%s) is a read-only device", mtd.node, args.node);
		goto out_close;
	}

	/* Make sure this MTD device is not attached to UBI */
	/* FIXME! Find a proper way to do this in barebox! */

	if (!args.quiet) {
		normsg_cont("%s (%s), size %lld bytes (%s)", mtd.node, mtd.type_str,
			mtd.size, size_human_readable(mtd.size));
		printf(", %d eraseblocks of %d bytes (%s)", mtd.eb_cnt,
			mtd.eb_size, size_human_readable(mtd.eb_size));
		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
	}

	if (args.quiet)
		verbose = 0;
	else if (args.verbose)
		verbose = 2;
	else
		verbose = 1;
	err = libscan_ubi_scan(&mtd, args.node_fd, &si, verbose);
	if (err) {
		errmsg("failed to scan %s (%s)", mtd.node, args.node);
		goto out_close;
	}

	if (si->good_cnt == 0) {
		errmsg("all %d eraseblocks are bad", si->bad_cnt);
		goto out_free;
	}

	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
		errmsg("too few non-bad eraseblocks (%d) on %s",
		       si->good_cnt, mtd.node);
		goto out_free;
	}

	if (!args.quiet) {
		if (si->ok_cnt)
			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
			       si->ok_cnt, si->mean_ec);
		if (si->empty_cnt)
			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
		if (si->corrupted_cnt)
			normsg("%d corrupted erase counters", si->corrupted_cnt);
		print_bad_eraseblocks(&mtd, si);
	}

	if (si->alien_cnt) {
		if (!args.quiet)
			warnmsg("%d of %d eraseblocks contain non-ubifs data",
				si->alien_cnt, si->good_cnt);
		if (!args.yes && !args.quiet)
			warnmsg("use '-y' to force erasing");
		if (!args.yes)
			goto out_free;
	}

	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
		int percent = (si->ok_cnt * 100) / si->good_cnt;

		/*
		 * Make sure the majority of eraseblocks have valid
		 * erase counters.
		 */
		if (percent < 50) {
			if (!args.quiet) {
				warnmsg("only %d of %d eraseblocks have valid erase counter",
					si->ok_cnt, si->good_cnt);
				if (args.yes) {
					normsg("erase counter 0 will be used for all eraseblocks");
					normsg("note, arbitrary erase counter value may be specified using -e option");

				} else {
					warnmsg("use '-y' to force erase counters");
				}
			}

			if (!args.yes)
				goto out_free;

			args.ec = 0;
			args.override_ec = 1;

		} else if (percent < 95) {
			if (!args.quiet) {
				warnmsg("only %d of %d eraseblocks have valid erase counter",
					si->ok_cnt, si->good_cnt);
				if (args.yes)
					normsg("mean erase counter %lld will be used for the rest of eraseblock",
					       si->mean_ec);
				else
					warnmsg("use '-y' to force erase counters");
			}

			if (!args.yes)
				goto out_free;

			args.ec = si->mean_ec;
			args.override_ec = 1;
		}
	}

	if (!args.quiet && args.override_ec)
		normsg("use erase counter %lld for all eraseblocks", args.ec);

	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, mtd.subpage_size,
			 args.vid_hdr_offs, args.ubi_ver, args.image_seq);

	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
		/*
		 * Hmm, what we read from flash and what we calculated using
		 * min. I/O unit size and sub-page size differs.
		 */
		if (!args.quiet) {
			warnmsg("VID header and data offsets on flash are %d and %d, "
				"which is different to requested offsets %d and %d",
				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
				ui.data_offs);
			normsg("using offsets %d and %d",  ui.vid_hdr_offs, ui.data_offs);
		}
	}

	if (args.image) {
		err = flash_image(&mtd, &ui, si);
		if (err < 0)
			goto out_free;

		err = format(&mtd, &ui, si, err, 1);
		if (err)
			goto out_free;
	} else {
		err = format(&mtd, &ui, si, 0, args.novtbl);
		if (err)
			goto out_free;
	}

	libscan_ubi_scan_free(si);
	close(args.node_fd);
	return 0;

out_free:
	libscan_ubi_scan_free(si);
out_close:
	close(args.node_fd);
out_close_mtd:
	return 1;
}
示例#23
0
void
rtsol_input(int s)
{
	u_char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
	int l, ifindex = 0, *hlimp = NULL;
	ssize_t msglen;
	struct in6_pktinfo *pi = NULL;
	struct ifinfo *ifi = NULL;
	struct ra_opt *rao = NULL;
	struct icmp6_hdr *icp;
	struct nd_router_advert *nd_ra;
	struct cmsghdr *cm;
	struct rainfo *rai;
	char *raoptp;
	char *p;
	struct in6_addr *addr;
	struct nd_opt_hdr *ndo;
	struct nd_opt_rdnss *rdnss;
	struct nd_opt_dnssl *dnssl;
	size_t len;
	char nsbuf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1];
	char dname[NI_MAXHOST];
	struct timeval now;
	struct timeval lifetime;
	int newent_rai;
	int newent_rao;

	/* get message.  namelen and controllen must always be initialized. */
	rcvmhdr.msg_namelen = sizeof(from);
	rcvmhdr.msg_controllen = rcvcmsglen;
	if ((msglen = recvmsg(s, &rcvmhdr, 0)) < 0) {
		warnmsg(LOG_ERR, __func__, "recvmsg: %s", strerror(errno));
		return;
	}

	/* extract optional information via Advanced API */
	for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&rcvmhdr); cm;
	    cm = (struct cmsghdr *)CMSG_NXTHDR(&rcvmhdr, cm)) {
		if (cm->cmsg_level == IPPROTO_IPV6 &&
		    cm->cmsg_type == IPV6_PKTINFO &&
		    cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
			pi = (struct in6_pktinfo *)(CMSG_DATA(cm));
			ifindex = pi->ipi6_ifindex;
		}
		if (cm->cmsg_level == IPPROTO_IPV6 &&
		    cm->cmsg_type == IPV6_HOPLIMIT &&
		    cm->cmsg_len == CMSG_LEN(sizeof(int)))
			hlimp = (int *)CMSG_DATA(cm);
	}

	if (ifindex == 0) {
		warnmsg(LOG_ERR, __func__,
		    "failed to get receiving interface");
		return;
	}
	if (hlimp == NULL) {
		warnmsg(LOG_ERR, __func__,
		    "failed to get receiving hop limit");
		return;
	}

	if ((size_t)msglen < sizeof(struct nd_router_advert)) {
		warnmsg(LOG_INFO, __func__,
		    "packet size(%zd) is too short", msglen);
		return;
	}

	icp = (struct icmp6_hdr *)rcvmhdr.msg_iov[0].iov_base;

	if (icp->icmp6_type != ND_ROUTER_ADVERT) {
		/*
		 * this should not happen because we configured a filter
		 * that only passes RAs on the receiving socket.
		 */
		warnmsg(LOG_ERR, __func__,
		    "invalid icmp type(%d) from %s on %s", icp->icmp6_type,
		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
			sizeof(ntopbuf)),
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
		return;
	}

	if (icp->icmp6_code != 0) {
		warnmsg(LOG_INFO, __func__,
		    "invalid icmp code(%d) from %s on %s", icp->icmp6_code,
		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
			sizeof(ntopbuf)),
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
		return;
	}

	if (*hlimp != 255) {
		warnmsg(LOG_INFO, __func__,
		    "invalid RA with hop limit(%d) from %s on %s",
		    *hlimp,
		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
			sizeof(ntopbuf)),
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
		return;
	}

	if (pi && !IN6_IS_ADDR_LINKLOCAL(&from.sin6_addr)) {
		warnmsg(LOG_INFO, __func__,
		    "invalid RA with non link-local source from %s on %s",
		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
			sizeof(ntopbuf)),
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
		return;
	}

	/* xxx: more validation? */

	if ((ifi = find_ifinfo(pi->ipi6_ifindex)) == NULL) {
		warnmsg(LOG_INFO, __func__,
		    "received RA from %s on an unexpected IF(%s)",
		    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
			sizeof(ntopbuf)),
		    if_indextoname(pi->ipi6_ifindex, ifnamebuf));
		return;
	}

	warnmsg(LOG_DEBUG, __func__,
	    "received RA from %s on %s, state is %d",
	    inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, sizeof(ntopbuf)),
	    ifi->ifname, ifi->state);

	nd_ra = (struct nd_router_advert *)icp;

	/*
	 * Process the "O bit."
	 * If the value of OtherConfigFlag changes from FALSE to TRUE, the
	 * host should invoke the stateful autoconfiguration protocol,
	 * requesting information.
	 * [RFC 2462 Section 5.5.3]
	 */
	if (((nd_ra->nd_ra_flags_reserved) & ND_RA_FLAG_OTHER) &&
	    !ifi->otherconfig) {
		warnmsg(LOG_DEBUG, __func__,
		    "OtherConfigFlag on %s is turned on", ifi->ifname);
		ifi->otherconfig = 1;
		CALL_SCRIPT(OTHER, NULL);
	}
	gettimeofday(&now, NULL);
	newent_rai = 0;
	rai = find_rainfo(ifi, &from);
	if (rai == NULL) {
		ELM_MALLOC(rai, exit(1));
		rai->rai_ifinfo = ifi;
		TAILQ_INIT(&rai->rai_ra_opt);
		rai->rai_saddr.sin6_family = AF_INET6;
		rai->rai_saddr.sin6_len = sizeof(rai->rai_saddr);
		memcpy(&rai->rai_saddr.sin6_addr, &from.sin6_addr,
		    sizeof(rai->rai_saddr.sin6_addr));
		newent_rai = 1;
	}

#define	RA_OPT_NEXT_HDR(x)	(struct nd_opt_hdr *)((char *)x + \
				(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
	/* Process RA options. */
	warnmsg(LOG_DEBUG, __func__, "Processing RA");
	raoptp = (char *)icp + sizeof(struct nd_router_advert);
	while (raoptp < (char *)icp + msglen) {
		ndo = (struct nd_opt_hdr *)raoptp;
		warnmsg(LOG_DEBUG, __func__, "ndo = %p", raoptp);
		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_type = %d",
		    ndo->nd_opt_type);
		warnmsg(LOG_DEBUG, __func__, "ndo->nd_opt_len = %d",
		    ndo->nd_opt_len);

		switch (ndo->nd_opt_type) {
		case ND_OPT_RDNSS:
			rdnss = (struct nd_opt_rdnss *)raoptp;

			/* Optlen sanity check (Section 5.3.1 in RFC 6106) */
			if (rdnss->nd_opt_rdnss_len < 3) {
				warnmsg(LOG_INFO, __func__,
		    			"too short RDNSS option"
					"in RA from %s was ignored.",
					inet_ntop(AF_INET6, &from.sin6_addr,
					    ntopbuf, sizeof(ntopbuf)));
				break;
			}

			addr = (struct in6_addr *)(raoptp + sizeof(*rdnss));
			while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) {
				if (inet_ntop(AF_INET6, addr, ntopbuf,
					sizeof(ntopbuf)) == NULL) {
					warnmsg(LOG_INFO, __func__,
		    			    "an invalid address in RDNSS option"
					    " in RA from %s was ignored.",
					    inet_ntop(AF_INET6, &from.sin6_addr,
						ntopbuf, sizeof(ntopbuf)));
					addr++;
					continue;
				}
				if (IN6_IS_ADDR_LINKLOCAL(addr))
					/* XXX: % has to be escaped here */
					l = snprintf(nsbuf, sizeof(nsbuf),
					    "%s%c%s", ntopbuf,
					    SCOPE_DELIMITER,
					    ifi->ifname);
				else
					l = snprintf(nsbuf, sizeof(nsbuf),
					    "%s", ntopbuf);
				if (l < 0 || (size_t)l >= sizeof(nsbuf)) {
					warnmsg(LOG_ERR, __func__,
					    "address copying error in "
					    "RDNSS option: %d.", l);
					addr++;
					continue;
				}
				warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
				    nsbuf);

				newent_rao = 0;
				rao = find_raopt(rai, ndo->nd_opt_type, nsbuf,
				    strlen(nsbuf));
				if (rao == NULL) {
					ELM_MALLOC(rao, break);
					rao->rao_type = ndo->nd_opt_type;
					rao->rao_len = strlen(nsbuf);
					rao->rao_msg = strdup(nsbuf);
					if (rao->rao_msg == NULL) {
						warnmsg(LOG_ERR, __func__,
						    "strdup failed: %s",
						    strerror(errno));
						free(rao);
						addr++;
						continue;
					}
					newent_rao = 1;
				}
				/* Set expiration timer */
				memset(&rao->rao_expire, 0,
				    sizeof(rao->rao_expire));
				memset(&lifetime, 0, sizeof(lifetime));
				lifetime.tv_sec =
				    ntohl(rdnss->nd_opt_rdnss_lifetime);
				timeradd(&now, &lifetime, &rao->rao_expire);

				if (newent_rao)
					TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
					    rao, rao_next);
				addr++;
			}
			break;
		case ND_OPT_DNSSL:
			dnssl = (struct nd_opt_dnssl *)raoptp;

			/* Optlen sanity check (Section 5.3.1 in RFC 6106) */
			if (dnssl->nd_opt_dnssl_len < 2) {
				warnmsg(LOG_INFO, __func__,
		    			"too short DNSSL option"
					"in RA from %s was ignored.",
					inet_ntop(AF_INET6, &from.sin6_addr,
					    ntopbuf, sizeof(ntopbuf)));
				break;
			}

			/*
			 * Ensure NUL-termination in DNSSL in case of
			 * malformed field.
			 */
			p = (char *)RA_OPT_NEXT_HDR(raoptp);
			*(p - 1) = '\0';

			p = raoptp + sizeof(*dnssl);
			while (1 < (len = dname_labeldec(dname, sizeof(dname),
			    p))) {
				/* length == 1 means empty string */
				warnmsg(LOG_DEBUG, __func__, "dname = %s",
				    dname);

				newent_rao = 0;
				rao = find_raopt(rai, ndo->nd_opt_type, dname,
				    strlen(dname));
				if (rao == NULL) {
					ELM_MALLOC(rao, break);
					rao->rao_type = ndo->nd_opt_type;
					rao->rao_len = strlen(dname);
					rao->rao_msg = strdup(dname);
					if (rao->rao_msg == NULL) {
						warnmsg(LOG_ERR, __func__,
						    "strdup failed: %s",
						    strerror(errno));
						free(rao);
						addr++;
						continue;
					}
					newent_rao = 1;
				}
				/* Set expiration timer */
				memset(&rao->rao_expire, 0,
				    sizeof(rao->rao_expire));
				memset(&lifetime, 0, sizeof(lifetime));
				lifetime.tv_sec =
				    ntohl(dnssl->nd_opt_dnssl_lifetime);
				timeradd(&now, &lifetime, &rao->rao_expire);

				if (newent_rao)
					TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
					    rao, rao_next);
				p += len;
			}
			break;
		default:  
			/* nothing to do for other options */
			break;
		}
示例#24
0
void
rtsol_timer_update(struct ifinfo *ifinfo)
{
#define MILLION 1000000
#define DADRETRY 10		/* XXX: adhoc */
	long interval;
	struct timeval now;

	bzero(&ifinfo->timer, sizeof(ifinfo->timer));

	switch (ifinfo->state) {
	case IFS_DOWN:
	case IFS_TENTATIVE:
		if (++ifinfo->dadcount > DADRETRY) {
			ifinfo->dadcount = 0;
			ifinfo->timer.tv_sec = PROBE_INTERVAL;
		}
		else
			ifinfo->timer.tv_sec = 1;
		break;
	case IFS_IDLE:
		if (mobile_node) {
			/* XXX should be configurable */ 
			ifinfo->timer.tv_sec = 3;
		}
		else
			ifinfo->timer = tm_max;	/* stop timer(valid?) */
		break;
	case IFS_DELAY:
#ifndef HAVE_ARC4RANDOM
		interval = random() % (MAX_RTR_SOLICITATION_DELAY * MILLION);
#else
		interval = arc4random() % (MAX_RTR_SOLICITATION_DELAY * MILLION);
#endif
		ifinfo->timer.tv_sec = interval / MILLION;
		ifinfo->timer.tv_usec = interval % MILLION;
		break;
	case IFS_PROBE:
		if (ifinfo->probes < MAX_RTR_SOLICITATIONS)
			ifinfo->timer.tv_sec = RTR_SOLICITATION_INTERVAL;
		else {
			/*
			 * After sending MAX_RTR_SOLICITATIONS solicitations,
			 * we're just waiting for possible replies; there
			 * will be no more solicatation.  Thus, we change
			 * the timer value to MAX_RTR_SOLICITATION_DELAY based
			 * on RFC 2461, Section 6.3.7.
			 */
			ifinfo->timer.tv_sec = MAX_RTR_SOLICITATION_DELAY;
		}
		break;
	default:
		warnmsg(LOG_ERR, __func__,
			"illegal interface state(%d) on %s",
			ifinfo->state, ifinfo->ifname);
		return;
	}

	/* reset the timer */
	if (TIMEVAL_EQ(ifinfo->timer, tm_max)) {
		ifinfo->expire = tm_max;
		warnmsg(LOG_DEBUG, __func__,
			"stop timer for %s", ifinfo->ifname);
	}
	else {
		gettimeofday(&now, NULL);
		TIMEVAL_ADD(&now, &ifinfo->timer, &ifinfo->expire);

		if (dflag > 1)
			warnmsg(LOG_DEBUG, __func__,
				"set timer for %s to %d:%d", ifinfo->ifname,
			       (int)ifinfo->timer.tv_sec,
			       (int)ifinfo->timer.tv_usec);
	}

#undef MILLION
}
示例#25
0
static struct timeval *
rtsol_check_timer(void)
{
	static struct timeval returnval;
	struct timeval now, rtsol_timer;
	struct ifinfo *ifinfo;
	int flags;

	gettimeofday(&now, NULL);

	rtsol_timer = tm_max;

	for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) {
		if (TIMEVAL_LEQ(ifinfo->expire, now)) {
			if (dflag > 1)
				warnmsg(LOG_DEBUG, __func__,
					"timer expiration on %s, "
				       "state = %d", ifinfo->ifname,
				       ifinfo->state);

			switch (ifinfo->state) {
			case IFS_DOWN:
			case IFS_TENTATIVE:
				/* interface_up returns 0 on success */
				flags = interface_up(ifinfo->ifname);
				if (flags == 0)
					ifinfo->state = IFS_DELAY;
				else if (flags == IFS_TENTATIVE)
					ifinfo->state = IFS_TENTATIVE;
				else
					ifinfo->state = IFS_DOWN;
				break;
			case IFS_IDLE:
			{
				int oldstatus = ifinfo->active;
				int probe = 0;

				ifinfo->active =
					interface_status(ifinfo);

				if (oldstatus != ifinfo->active) {
					warnmsg(LOG_DEBUG, __func__,
						"%s status is changed"
						" from %d to %d",
						ifinfo->ifname,
						oldstatus, ifinfo->active);
					probe = 1;
					ifinfo->state = IFS_DELAY;
				}
				else if (ifinfo->probeinterval &&
					 (ifinfo->probetimer -=
					  ifinfo->timer.tv_sec) <= 0) {
					/* probe timer expired */
					ifinfo->probetimer =
						ifinfo->probeinterval;
					probe = 1;
					ifinfo->state = IFS_PROBE;
				}

				if (probe && mobile_node)
					defrouter_probe(ifinfo->sdl->sdl_index);
				break;
			}
			case IFS_DELAY:
				ifinfo->state = IFS_PROBE;
				sendpacket(ifinfo);
				break;
			case IFS_PROBE:
				if (ifinfo->probes < MAX_RTR_SOLICITATIONS)
					sendpacket(ifinfo);
				else {
					warnmsg(LOG_INFO, __func__,
						"No answer "
						"after sending %d RSs",
						ifinfo->probes);
					ifinfo->probes = 0;
					ifinfo->state = IFS_IDLE;
				}
				break;
			}
			rtsol_timer_update(ifinfo);
		}

		if (TIMEVAL_LT(ifinfo->expire, rtsol_timer))
			rtsol_timer = ifinfo->expire;
	}

	if (TIMEVAL_EQ(rtsol_timer, tm_max)) {
		warnmsg(LOG_DEBUG, __func__, "there is no timer");
		return(NULL);
	}
	else if (TIMEVAL_LT(rtsol_timer, now))
		/* this may occur when the interval is too small */
		returnval.tv_sec = returnval.tv_usec = 0;
	else
		TIMEVAL_SUB(&rtsol_timer, &now, &returnval);

	if (dflag > 1)
		warnmsg(LOG_DEBUG, __func__, "New timer is %ld:%08ld",
			(long)returnval.tv_sec, (long)returnval.tv_usec);

	return(&returnval);
}
示例#26
0
int ubi_scan(struct mtd_dev_info *mtd, int fd, struct ubi_scan_info **info,
	     int verbose)
{
	int eb, v = (verbose == 2), pr = (verbose == 1);
	struct ubi_scan_info *si;
	unsigned long long sum = 0;

	si = calloc(1, sizeof(struct ubi_scan_info));
	if (!si)
		return sys_errmsg("cannot allocate %zd bytes of memory",
				  sizeof(struct ubi_scan_info));

	si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t));
	if (!si->ec) {
		sys_errmsg("cannot allocate %zd bytes of memory",
			   sizeof(struct ubi_scan_info));
		goto out_si;
	}

	si->vid_hdr_offs = si->data_offs = -1;

	verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt);
	for (eb = 0; eb < mtd->eb_cnt; eb++) {
		int ret;
		uint32_t crc;
		struct ubi_ec_hdr ech;
		unsigned long long ec;

		if (v) {
			normsg_cont("scanning eraseblock %d", eb);
			fflush(stdout);
		}
		if (pr) {
			printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete  ",
			       eb, (long long)(eb + 1) * 100 / mtd->eb_cnt);
			fflush(stdout);
		}

		ret = mtd_is_bad(mtd, fd, eb);
		if (ret == -1)
			goto out_ec;
		if (ret) {
			si->bad_cnt += 1;
			si->ec[eb] = EB_BAD;
			if (v)
				printf(": bad\n");
			continue;
		}

		ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr));
		if (ret < 0)
			goto out_ec;

		if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) {
			if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) {
				si->empty_cnt += 1;
				si->ec[eb] = EB_EMPTY;
				if (v)
					printf(": empty\n");
			} else {
				si->alien_cnt += 1;
				si->ec[eb] = EB_ALIEN;
				if (v)
					printf(": alien\n");
			}
			continue;
		}

		crc = mtd_crc32(UBI_CRC32_INIT, &ech, UBI_EC_HDR_SIZE_CRC);
		if (be32_to_cpu(ech.hdr_crc) != crc) {
			si->corrupted_cnt += 1;
			si->ec[eb] = EB_CORRUPTED;
			if (v)
				printf(": bad CRC %#08x, should be %#08x\n",
				       crc, be32_to_cpu(ech.hdr_crc));
			continue;
		}

		ec = be64_to_cpu(ech.ec);
		if (ec > EC_MAX) {
			if (pr)
				printf("\n");
			errmsg("erase counter in EB %d is %llu, while this "
			       "program expects them to be less than %u",
			       eb, ec, EC_MAX);
			goto out_ec;
		}

		if (si->vid_hdr_offs == -1) {
			si->vid_hdr_offs = be32_to_cpu(ech.vid_hdr_offset);
			si->data_offs = be32_to_cpu(ech.data_offset);
			if (si->data_offs % mtd->min_io_size) {
				if (pr)
					printf("\n");
				if (v)
					printf(": corrupted because of the below\n");
				warnmsg("bad data offset %d at eraseblock %d (n"
					"of multiple of min. I/O unit size %d)",
					si->data_offs, eb, mtd->min_io_size);
				warnmsg("treat eraseblock %d as corrupted", eb);
				si->corrupted_cnt += 1;
				si->ec[eb] = EB_CORRUPTED;
				continue;

			}
		} else {
			if ((int)be32_to_cpu(ech.vid_hdr_offset) != si->vid_hdr_offs) {
				if (pr)
					printf("\n");
				if (v)
					printf(": corrupted because of the below\n");
				warnmsg("inconsistent VID header offset: was "
					"%d, but is %d in eraseblock %d",
					si->vid_hdr_offs,
					be32_to_cpu(ech.vid_hdr_offset), eb);
				warnmsg("treat eraseblock %d as corrupted", eb);
				si->corrupted_cnt += 1;
				si->ec[eb] = EB_CORRUPTED;
				continue;
			}
			if ((int)be32_to_cpu(ech.data_offset) != si->data_offs) {
				if (pr)
					printf("\n");
				if (v)
					printf(": corrupted because of the below\n");
				warnmsg("inconsistent data offset: was %d, but"
					" is %d in eraseblock %d",
					si->data_offs,
					be32_to_cpu(ech.data_offset), eb);
				warnmsg("treat eraseblock %d as corrupted", eb);
				si->corrupted_cnt += 1;
				si->ec[eb] = EB_CORRUPTED;
				continue;
			}
		}

		si->ok_cnt += 1;
		si->ec[eb] = ec;
		if (v)
			printf(": OK, erase counter %u\n", si->ec[eb]);
	}

	if (si->ok_cnt != 0) {
		/* Calculate mean erase counter */
		for (eb = 0; eb < mtd->eb_cnt; eb++) {
			if (si->ec[eb] > EC_MAX)
				continue;
			sum += si->ec[eb];
		}
		si->mean_ec = sum / si->ok_cnt;
	}

	si->good_cnt = mtd->eb_cnt - si->bad_cnt;
	verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d "
		"alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt,
		si->empty_cnt, si->alien_cnt, si->bad_cnt);

	*info = si;
	if (pr)
		printf("\n");
	return 0;

out_ec:
	free(si->ec);
out_si:
	free(si);
	*info = NULL;
	return -1;
}
示例#27
0
static int
ifconfig(char *ifname)
{
	struct ifinfo *ifinfo;
	struct sockaddr_dl *sdl;
	int flags;

	if ((sdl = if_nametosdl(ifname)) == NULL) {
		warnmsg(LOG_ERR, __func__,
		       "failed to get link layer information for %s", ifname);
		return(-1);
	}
	if (find_ifinfo(sdl->sdl_index)) {
		warnmsg(LOG_ERR, __func__,
			"interface %s was already configured", ifname);
		free(sdl);
		return(-1);
	}

	if ((ifinfo = malloc(sizeof(*ifinfo))) == NULL) {
		warnmsg(LOG_ERR, __func__, "memory allocation failed");
		free(sdl);
		return(-1);
	}
	memset(ifinfo, 0, sizeof(*ifinfo));
	ifinfo->sdl = sdl;

	strncpy(ifinfo->ifname, ifname, sizeof(ifinfo->ifname));

	/* construct a router solicitation message */
	if (make_packet(ifinfo))
		goto bad;

	/*
	 * check if the interface is available.
	 * also check if SIOCGIFMEDIA ioctl is OK on the interface.
	 */
	ifinfo->mediareqok = 1;
	ifinfo->active = interface_status(ifinfo);
	if (!ifinfo->mediareqok) {
		/*
		 * probe routers periodically even if the link status
		 * does not change.
		 */
		ifinfo->probeinterval = PROBE_INTERVAL;
	}

	/* activate interface: interface_up returns 0 on success */
	flags = interface_up(ifinfo->ifname);
	if (flags == 0)
		ifinfo->state = IFS_DELAY;
	else if (flags == IFS_TENTATIVE)
		ifinfo->state = IFS_TENTATIVE;
	else
		ifinfo->state = IFS_DOWN;

	rtsol_timer_update(ifinfo);

	/* link into chain */
	if (iflist)
		ifinfo->next = iflist;
	iflist = ifinfo;

	return(0);

  bad:
	free(ifinfo->sdl);
	free(ifinfo);
	return(-1);
}
示例#28
0
int
main(int argc, char *argv[])
{
	int s, rtsock, maxfd, ch;
	int once = 0;
	struct timeval *timeout;
	struct fd_set fdset;
	char *argv0;
	const char *opts;

	/*
	 * Initialization
	 */
	argv0 = argv[0];

	/* get option */
	if (argv0 && argv0[strlen(argv0) - 1] != 'd') {
		fflag = 1;
		once = 1;
		opts = "adD";
	} else
		opts = "adDfm1";

	while ((ch = getopt(argc, argv, opts)) != -1) {
		switch (ch) {
		case 'a':
			aflag = 1;
			break;
		case 'd':
			dflag = 1;
			break;
		case 'D':
			dflag = 2;
			break;
		case 'f':
			fflag = 1;
			break;
		case 'm':
			mobile_node = 1;
			break;
		case '1':
			once = 1;
			break;
		default:
			usage(argv0);
			/*NOTREACHED*/
		}
	}
	argc -= optind;
	argv += optind;

	if (aflag) {
		int i;

		if (argc != 0) {
			usage(argv0);
			/*NOTREACHED*/
		}

		argv = autoifprobe();
		if (!argv) {
			errx(1, "could not autoprobe interface");
			/*NOTREACHED*/
		}

		for (i = 0; argv[i]; i++)
			;
		argc = i;
	}
	if (argc == 0) {
		usage(argv0);
		/*NOTREACHED*/
	}

	/* set log level */
	if (dflag == 0)
		log_upto = LOG_NOTICE;
	if (!fflag) {
		char *ident;
		ident = strrchr(argv0, '/');
		if (!ident)
			ident = argv0;
		else
			ident++;
		openlog(ident, LOG_NDELAY|LOG_PID, LOG_DAEMON);
		if (log_upto >= 0)
			setlogmask(LOG_UPTO(log_upto));
	}

#ifndef HAVE_ARC4RANDOM
	/* random value initilization */
	srandom((u_long)time(NULL));
#endif

	/* warn if accept_rtadv is down */
	if (!getinet6sysctl(IPV6CTL_ACCEPT_RTADV))
		warnx("kernel is configured not to accept RAs");
	/* warn if forwarding is up */
	if (getinet6sysctl(IPV6CTL_FORWARDING))
		warnx("kernel is configured as a router, not a host");

	/* initialization to dump internal status to a file */
	if (signal(SIGUSR1, rtsold_set_dump_file) == SIG_ERR) {
		errx(1, "failed to set signal for dump status");
		/*NOTREACHED*/
	}

	/*
	 * Open a socket for sending RS and receiving RA.
	 * This should be done before calling ifinit(), since the function
	 * uses the socket.
	 */
	if ((s = sockopen()) < 0) {
		errx(1, "failed to open a socket");
		/*NOTREACHED*/
	}
	maxfd = s;
	if ((rtsock = rtsock_open()) < 0) {
		errx(1, "failed to open a socket");
		/*NOTREACHED*/
	}
	if (rtsock > maxfd)
		maxfd = rtsock;

	/* configuration per interface */
	if (ifinit()) {
		errx(1, "failed to initilizatoin interfaces");
		/*NOTREACHED*/
	}
	while (argc--) {
		if (ifconfig(*argv)) {
			errx(1, "failed to initialize %s", *argv);
			/*NOTREACHED*/
		}
		argv++;
	}

	/* setup for probing default routers */
	if (probe_init()) {
		errx(1, "failed to setup for probing routers");
		/*NOTREACHED*/
	}

	if (!fflag)
		daemon(0, 0);		/* act as a daemon */

	/* dump the current pid */
	if (!once) {
		pid_t pid = getpid();
		FILE *fp;

		if ((fp = fopen(pidfilename, "w")) == NULL)
			warnmsg(LOG_ERR, __func__,
				"failed to open a log file(%s): %s",
				pidfilename, strerror(errno));
		else {
			fprintf(fp, "%d\n", pid);
			fclose(fp);
		}
	}

	FD_ZERO(&fdset);
	FD_SET(s, &fdset);
	FD_SET(rtsock, &fdset);
	while (1) {		/* main loop */
		int e;
		struct fd_set select_fd = fdset;

		if (do_dump) {	/* SIGUSR1 */
			do_dump = 0;
			rtsold_dump_file(dumpfilename);
		}
			
		timeout = rtsol_check_timer();

		if (once) {
			struct ifinfo *ifi;

			/* if we have no timeout, we are done (or failed) */
			if (timeout == NULL)
				break;

			/* if all interfaces have got RA packet, we are done */
			for (ifi = iflist; ifi; ifi = ifi->next) {
				if (ifi->state != IFS_DOWN && ifi->racnt == 0)
					break;
			}
			if (ifi == NULL)
				break;
		}
		e = select(maxfd + 1, &select_fd, NULL, NULL, timeout);
		if (e < 1) {
			if (e < 0 && errno != EINTR) {
				warnmsg(LOG_ERR, __func__, "select: %s",
				       strerror(errno));
			}
			continue;
		}

		/* packet reception */
		if (FD_ISSET(rtsock, &select_fd))
			rtsock_input(rtsock);
		if (FD_ISSET(s, &select_fd))
			rtsol_input(s);
	}
	/* NOTREACHED */

	return 0;
}
示例#29
0
int main(int argc, char * const argv[])
{
	int err, verbose;
	struct mtd_info mtd;
	libubi_t libubi;
	struct ubigen_info ui;
	struct ubi_scan_info *si;

	err = parse_opt(argc, argv);
	if (err)
		return -1;

	err = mtd_get_info(args.node, &mtd);
	if (err)
		return errmsg("cannot get information about \"%s\"", args.node);

	if (args.subpage_size == 0)
		args.subpage_size = mtd.min_io_size;
	else {
		if (args.subpage_size > mtd.min_io_size) {
			errmsg("sub-page cannot be larger than min. I/O unit");
			goto out_close;
		}

		if (mtd.min_io_size % args.subpage_size) {
			errmsg("min. I/O unit size should be multiple of sub-page size");
			goto out_close;
		}
	}

	/* Validate VID header offset if it was specified */
	if (args.vid_hdr_offs != 0) {
		if (args.vid_hdr_offs % 8) {
			errmsg("VID header offset has to be multiple of min. I/O unit size");
			goto out_close;
		}
		if (args.vid_hdr_offs + UBI_VID_HDR_SIZE > mtd.eb_size) {
			errmsg("bad VID header offset");
			goto out_close;
		}
	}

	/*
	 * Because of MTD interface limitations 'mtd_get_info()' cannot get
	 * sub-page so we force the user to pass it via the command line. Let's
	 * hope the user passed us something sane.
	 */
	mtd.subpage_size = args.subpage_size;

	if (mtd.rdonly) {
		errmsg("mtd%d (%s) is a read-only device", mtd.num, args.node);
		goto out_close;
	}

	/* Make sure this MTD device is not attached to UBI */
	libubi = libubi_open(0);
	if (libubi) {
		int ubi_dev_num;

		err = mtd_num2ubi_dev(libubi, mtd.num, &ubi_dev_num);
		libubi_close(libubi);
		if (!err) {
			errmsg("please, first detach mtd%d (%s) from ubi%d",
			       mtd.num, args.node, ubi_dev_num);
			goto out_close;
		}
	}

	if (!args.quiet) {
		normsg_cont("mtd%d (%s), size ", mtd.num, mtd.type_str);
		ubiutils_print_bytes(mtd.size, 1);
		printf(", %d eraseblocks of ", mtd.eb_size);
		ubiutils_print_bytes(mtd.eb_size, 1);
		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
	}

	if (args.quiet)
		verbose = 0;
	else if (args.verbose)
		verbose = 2;
	else
		verbose = 1;
	err = ubi_scan(&mtd, &si, verbose);
	if (err) {
		errmsg("failed to scan mtd%d (%s)", mtd.num, args.node);
		goto out_close;
	}

	if (si->good_cnt == 0) {
		errmsg("all %d eraseblocks are bad", si->bad_cnt);
		goto out_free;
	}

	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
		errmsg("too few non-bad eraseblocks (%d) on mtd%d", si->good_cnt, mtd.num);
		goto out_free;
	}

	if (!args.quiet) {
		if (si->ok_cnt)
			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
			       si->ok_cnt, si->mean_ec);
		if (si->empty_cnt)
			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
		if (si->corrupted_cnt)
			normsg("%d corrupted erase counters", si->corrupted_cnt);
		print_bad_eraseblocks(&mtd, si);
	}

	if (si->alien_cnt) {
		if (!args.yes || !args.quiet)
			warnmsg("%d of %d eraseblocks contain non-ubifs data",
				si->alien_cnt, si->good_cnt);
		if (!args.yes && want_exit()) {
			if (args.yes && !args.quiet)
				printf("yes\n");
			goto out_free;
		}
	}

	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
		int percent = ((double)si->ok_cnt)/si->good_cnt * 100;

		/*
		 * Make sure the majority of eraseblocks have valid
		 * erase counters.
		 */
		if (percent < 50) {
			if (!args.yes || !args.quiet)
				warnmsg("only %d of %d eraseblocks have valid erase counter",
					si->ok_cnt, si->good_cnt);
				normsg("erase counter 0 will be used for all eraseblocks");
				normsg("note, arbitrary erase counter value may be specified using -e option");
			if (!args.yes && want_exit()) {
				if (args.yes && !args.quiet)
					printf("yes\n");
				goto out_free;
			}
			 args.ec = 0;
			 args.override_ec = 1;
		} else if (percent < 95) {
			if (!args.yes || !args.quiet)
				warnmsg("only %d of %d eraseblocks have valid erase counter",
					si->ok_cnt, si->good_cnt);
				normsg("mean erase counter %lld will be used for the rest of eraseblock",
				       si->mean_ec);
			if (!args.yes && want_exit()) {
				if (args.yes && !args.quiet)
					printf("yes\n");
				goto out_free;
			}
			args.ec = si->mean_ec;
			args.override_ec = 1;
		}
	}

	if (!args.quiet && args.override_ec)
		normsg("use erase counter %lld for all eraseblocks", args.ec);

	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, args.subpage_size,
			 args.vid_hdr_offs, args.ubi_ver);

	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
		/*
		 * Hmm, what we read from flash and what we calculated using
		 * min. I/O unit size and sub-page size differs.
		 */
		if (!args.yes || !args.quiet) {
			warnmsg("VID header and data offsets on flash are %d and %d, "
				"which is different to calculated offsets %d and %d",
				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
				ui.data_offs);
			normsg_cont("use new offsets %d and %d? (yes/no)  ",
				    si->vid_hdr_offs, si->data_offs);
		}
		if (args.yes || answer_is_yes()) {
			if (args.yes && !args.quiet)
				printf("yes\n");
		} else {
			ui.vid_hdr_offs = si->vid_hdr_offs;
			ui.data_offs = si->data_offs;
		}
	}

	if (args.image) {
		err = flash_image(&mtd, &ui, si);
		if (err < 0)
			goto out_free;

		err = format(&mtd, &ui, si, err, 1);
		if (err)
			goto out_free;
	} else {
		err = format(&mtd, &ui, si, 0, args.novtbl);
		if (err)
			goto out_free;
	}

	ubi_scan_free(si);
	close(mtd.fd);
	return 0;

out_free:
	ubi_scan_free(si);
out_close:
	close(mtd.fd);
	return -1;
}
示例#30
0
int
sockopen(void)
{
	static u_char *rcvcmsgbuf = NULL, *sndcmsgbuf = NULL;
	int sndcmsglen, on;
	static u_char answer[1500];
	struct icmp6_filter filt;

	sndcmsglen = rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
	    CMSG_SPACE(sizeof(int));
	if (rcvcmsgbuf == NULL && (rcvcmsgbuf = malloc(rcvcmsglen)) == NULL) {
		warnmsg(LOG_ERR, __func__,
		    "malloc for receive msghdr failed");
		return (-1);
	}
	if (sndcmsgbuf == NULL && (sndcmsgbuf = malloc(sndcmsglen)) == NULL) {
		warnmsg(LOG_ERR, __func__,
		    "malloc for send msghdr failed");
		return (-1);
	}
	if ((rssock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
		warnmsg(LOG_ERR, __func__, "socket: %s", strerror(errno));
		return (-1);
	}

	/* specify to tell receiving interface */
	on = 1;
	if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
	    sizeof(on)) < 0) {
		warnmsg(LOG_ERR, __func__, "IPV6_RECVPKTINFO: %s",
		    strerror(errno));
		exit(1);
	}

	/* specify to tell value of hoplimit field of received IP6 hdr */
	on = 1;
	if (setsockopt(rssock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
	    sizeof(on)) < 0) {
		warnmsg(LOG_ERR, __func__, "IPV6_RECVHOPLIMIT: %s",
		    strerror(errno));
		exit(1);
	}

	/* specfiy to accept only router advertisements on the socket */
	ICMP6_FILTER_SETBLOCKALL(&filt);
	ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
	if (setsockopt(rssock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
	    sizeof(filt)) == -1) {
		warnmsg(LOG_ERR, __func__, "setsockopt(ICMP6_FILTER): %s",
		    strerror(errno));
		return(-1);
	}

	/* initialize msghdr for receiving packets */
	rcviov[0].iov_base = (caddr_t)answer;
	rcviov[0].iov_len = sizeof(answer);
	rcvmhdr.msg_name = (caddr_t)&from;
	rcvmhdr.msg_iov = rcviov;
	rcvmhdr.msg_iovlen = 1;
	rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;

	/* initialize msghdr for sending packets */
	sndmhdr.msg_namelen = sizeof(struct sockaddr_in6);
	sndmhdr.msg_iov = sndiov;
	sndmhdr.msg_iovlen = 1;
	sndmhdr.msg_control = (caddr_t)sndcmsgbuf;
	sndmhdr.msg_controllen = sndcmsglen;

	return (rssock);
}