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); }
/* * 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); }
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++; }
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"); }
/* 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); }
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; }
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); }
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; }
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); }
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); }
/* * 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; }
/* * 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); }
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); }
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; } }
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); } }
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); } }
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); }
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; }
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; }
/* 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 }
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; } }
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; }
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; }
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 }
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); }
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; }
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); }
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; }
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; }
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); }