/* * Delete routes associated with our interface */ void route_IfDelete(struct bundle *bundle, int all) { struct rt_msghdr *rtm; struct sockaddr *sa[RTAX_MAX]; struct ncprange range; int pass; size_t needed; char *sp, *cp, *ep; int mib[6]; log_Printf(LogDEBUG, "route_IfDelete (%d)\n", bundle->iface->index); mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_DUMP; mib[5] = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { log_Printf(LogERROR, "route_IfDelete: sysctl: estimate: %s\n", strerror(errno)); return; } sp = malloc(needed); if (sp == NULL) return; if (sysctl(mib, 6, sp, &needed, NULL, 0) < 0) { log_Printf(LogERROR, "route_IfDelete: sysctl: getroute: %s\n", strerror(errno)); free(sp); return; } ep = sp + needed; for (pass = 0; pass < 2; pass++) { /* * We do 2 passes. The first deletes all cloned routes. The second * deletes all non-cloned routes. This is done to avoid * potential errors from trying to delete route X after route Y where * route X was cloned from route Y (and is no longer there 'cos it * may have gone with route Y). */ if (RTF_WASCLONED == 0 && pass == 0) /* So we can't tell ! */ continue; for (cp = sp; cp < ep; cp += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)cp; route_ParseHdr(rtm, sa); if (rtm->rtm_index == bundle->iface->index && sa[RTAX_DST] && sa[RTAX_GATEWAY] && (sa[RTAX_DST]->sa_family == AF_INET #ifndef NOINET6 || sa[RTAX_DST]->sa_family == AF_INET6 #endif ) && (all || (rtm->rtm_flags & RTF_GATEWAY))) { if (log_IsKept(LogDEBUG)) { char gwstr[41]; struct ncpaddr gw; ncprange_setsa(&range, sa[RTAX_DST], sa[RTAX_NETMASK]); ncpaddr_setsa(&gw, sa[RTAX_GATEWAY]); snprintf(gwstr, sizeof gwstr, "%s", ncpaddr_ntoa(&gw)); log_Printf(LogDEBUG, "Found %s %s\n", ncprange_ntoa(&range), gwstr); } if (sa[RTAX_GATEWAY]->sa_family == AF_INET || #ifndef NOINET6 sa[RTAX_GATEWAY]->sa_family == AF_INET6 || #endif sa[RTAX_GATEWAY]->sa_family == AF_LINK) { if ((pass == 0 && (rtm->rtm_flags & RTF_WASCLONED)) || (pass == 1 && !(rtm->rtm_flags & RTF_WASCLONED))) { ncprange_setsa(&range, sa[RTAX_DST], sa[RTAX_NETMASK]); rt_Set(bundle, RTM_DELETE, &range, NULL, 0, 0); } else log_Printf(LogDEBUG, "route_IfDelete: Skip it (pass %d)\n", pass); } else log_Printf(LogDEBUG, "route_IfDelete: Can't remove routes for family %d\n", sa[RTAX_GATEWAY]->sa_family); } } } free(sp); }
static void server_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) { struct server *s = descriptor2server(d); struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *)&ss; struct sockaddr_in *sin = (struct sockaddr_in *)&ss; #ifndef NOINET6 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; #endif int ssize = sizeof ss, wfd; struct prompt *p; struct ncpaddr addr; if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) { wfd = accept(s->fd, sa, &ssize); if (wfd < 0) log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); else if (sa->sa_len == 0) { close(wfd); wfd = -1; } } else wfd = -1; if (wfd >= 0) switch (sa->sa_family) { case AF_LOCAL: log_Printf(LogPHASE, "Connected to local client.\n"); break; case AF_INET: ncpaddr_setsa(&addr, sa); if (ntohs(sin->sin_port) < 1024) { log_Printf(LogALERT, "Rejected client connection from %s:%u" "(invalid port number) !\n", ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); close(wfd); wfd = -1; break; } log_Printf(LogPHASE, "Connected to client from %s:%u\n", ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); break; #ifndef NOINET6 case AF_INET6: ncpaddr_setsa(&addr, sa); if (ntohs(sin6->sin6_port) < 1024) { log_Printf(LogALERT, "Rejected client connection from %s:%u" "(invalid port number) !\n", ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); close(wfd); wfd = -1; break; } log_Printf(LogPHASE, "Connected to client from %s:%u\n", ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); break; #endif default: write(wfd, "Unrecognised access !\n", 22); close(wfd); wfd = -1; break; } if (wfd >= 0) { if ((p = prompt_Create(s, bundle, wfd)) == NULL) { write(wfd, "Connection refused.\n", 20); close(wfd); } else { switch (sa->sa_family) { case AF_LOCAL: p->src.type = "local"; strncpy(p->src.from, s->cfg.sockname, sizeof p->src.from - 1); p->src.from[sizeof p->src.from - 1] = '\0'; break; case AF_INET: p->src.type = "ip"; snprintf(p->src.from, sizeof p->src.from, "%s:%u", ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); break; #ifndef NOINET6 case AF_INET6: p->src.type = "ip6"; snprintf(p->src.from, sizeof p->src.from, "%s:%u", ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); break; #endif } prompt_TtyCommandMode(p); prompt_Required(p); } } log_PromptListChanged = 0; for (p = log_PromptList(); p; p = p->next) if (descriptor_IsSet(&p->desc, fdset)) { descriptor_Read(&p->desc, bundle, fdset); if (log_PromptListChanged) break; } }
struct iface * iface_Create(const char *name) { int mib[6], maxtries, err; size_t needed, namelen; char *buf, *ptr, *end; struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct sockaddr_dl *dl; struct sockaddr *sa[RTAX_MAX]; struct iface *iface; struct iface_addr *addr; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = 0; mib[4] = NET_RT_IFLIST; mib[5] = 0; maxtries = 20; err = 0; do { if (maxtries-- == 0 || (err && err != ENOMEM)) { fprintf(stderr, "iface_Create: sysctl: %s\n", strerror(err)); return NULL; } if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { fprintf(stderr, "iface_Create: sysctl: estimate: %s\n", strerror(errno)); return NULL; } if ((buf = (char *)malloc(needed)) == NULL) { fprintf(stderr, "iface_Create: malloc failed: %s\n", strerror(errno)); return NULL; } if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { err = errno; free(buf); buf = NULL; } } while (buf == NULL); ptr = buf; end = buf + needed; iface = NULL; namelen = strlen(name); while (ptr < end && iface == NULL) { ifm = (struct if_msghdr *)ptr; /* On if_msghdr */ if (ifm->ifm_type != RTM_IFINFO) break; dl = (struct sockaddr_dl *)(ifm + 1); /* Single _dl at end */ if (dl->sdl_nlen == namelen && !strncmp(name, dl->sdl_data, namelen)) { iface = (struct iface *)malloc(sizeof *iface); if (iface == NULL) { fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno)); return NULL; } iface->name = strdup(name); iface->descr = NULL; iface->index = ifm->ifm_index; iface->flags = ifm->ifm_flags; iface->mtu = 0; iface->addrs = 0; iface->addr = NULL; } ptr += ifm->ifm_msglen; /* First ifa_msghdr */ for (; ptr < end; ptr += ifam->ifam_msglen) { ifam = (struct ifa_msghdr *)ptr; /* Next if address */ if (ifam->ifam_type != RTM_NEWADDR) /* finished this if */ break; if (iface != NULL && ifam->ifam_addrs & RTA_IFA) { /* Found a configured interface ! */ iface_ParseHdr(ifam, sa); if (sa[RTAX_IFA] && (sa[RTAX_IFA]->sa_family == AF_INET #ifndef NOINET6 || sa[RTAX_IFA]->sa_family == AF_INET6 #endif )) { /* Record the address */ addr = (struct iface_addr *) realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]); if (addr == NULL) break; iface->addr = addr; addr += iface->addrs; iface->addrs++; ncprange_setsa(&addr->ifa, sa[RTAX_IFA], sa[RTAX_NETMASK]); if (sa[RTAX_BRD]) ncpaddr_setsa(&addr->peer, sa[RTAX_BRD]); else ncpaddr_init(&addr->peer); } } } } free(buf); return iface; }
struct iface * iface_Create(const char *name) { size_t namelen; struct sockaddr_dl *dl; struct ifaddrs *ifap, *ifa; struct iface *iface; struct iface_addr *addr; if (getifaddrs(&ifap) != 0) { fprintf(stderr, "iface_Create: getifaddrs: %s\n", strerror(errno)); return NULL; } iface = NULL; namelen = strlen(name); for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { if (strcmp(name, ifa->ifa_name)) continue; if (ifa->ifa_addr->sa_family == AF_LINK) { dl = (struct sockaddr_dl *)ifa->ifa_addr; iface = (struct iface *)malloc(sizeof *iface); if (iface == NULL) { fprintf(stderr, "iface_Create: malloc: %s\n", strerror(errno)); freeifaddrs(ifap); return NULL; } iface->name = strdup(name); iface->index = if_nametoindex(name); iface->flags = ifa->ifa_flags; iface->mtu = 0; iface->addrs = 0; iface->addr = NULL; } if (ifa->ifa_addr->sa_family == AF_INET #ifndef NOINET6 || ifa->ifa_addr->sa_family == AF_INET6 #endif ) { /* Record the address */ addr = (struct iface_addr *) realloc(iface->addr, (iface->addrs + 1) * sizeof iface->addr[0]); if (addr == NULL) break; iface->addr = addr; addr += iface->addrs; iface->addrs++; ncprange_setsa(&addr->ifa, ifa->ifa_addr, ifa->ifa_netmask); if (ifa->ifa_broadaddr) ncpaddr_setsa(&addr->peer, ifa->ifa_broadaddr); else ncpaddr_init(&addr->peer); } } freeifaddrs(ifap); return iface; }