void handle_carrier(int carrier, int flags, const char *ifname) { struct interface *ifp; if (!(options & DHCPCD_LINK)) return; ifp = find_interface(ifname); if (ifp == NULL) { handle_interface(1, ifname); return; } if (!(ifp->options->options & DHCPCD_LINK)) return; if (carrier == LINK_UNKNOWN) carrier = carrier_status(ifp); /* will set ifp->flags */ else ifp->flags = flags; if (carrier == LINK_UNKNOWN) syslog(LOG_ERR, "%s: carrier_status: %m", ifname); /* IFF_RUNNING is checked, if needed, earlier and is OS dependant */ else if (carrier == LINK_DOWN || (ifp->flags & IFF_UP) == 0) { if (ifp->carrier != LINK_DOWN) { if (ifp->carrier == LINK_UP) syslog(LOG_INFO, "%s: carrier lost", ifp->name); ifp->carrier = LINK_DOWN; dhcp_close(ifp); dhcp6_drop(ifp, "EXPIRE6"); ipv6rs_drop(ifp); /* Don't blindly delete our knowledge of LL addresses. * We need to listen to what the kernel does with * them as some OS's will remove, mark tentative or * do nothing. */ ipv6_free_ll_callbacks(ifp); dhcp_drop(ifp, "NOCARRIER"); } } else if (carrier == LINK_UP && ifp->flags & IFF_UP) { if (ifp->carrier != LINK_UP) { syslog(LOG_INFO, "%s: carrier acquired", ifp->name); ifp->carrier = LINK_UP; #if !defined(__linux__) && !defined(__NetBSD__) /* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the * hardware address changes so we have to go * through the disovery process to work it out. */ handle_interface(0, ifp->name); #endif if (ifp->wireless) getifssid(ifp->name, ifp->ssid); configure_interface(ifp, margc, margv); script_runreason(ifp, "CARRIER"); start_interface(ifp); } } }
bool part_ui::render_floating_images() { events::raise_draw_event(); update_whole_screen(); skip_ = false; last_key_ = true; size_t fi_n = 0; foreach(floating_image::render_input& ri, imgs_) { const floating_image& fi = p_.get_floating_images()[fi_n]; if(!ri.image.null()) { sdl_blit(ri.image, NULL, video_.getSurface(), &ri.rect); update_rect(ri.rect); } if (!skip_) { int delay = fi.display_delay(), delay_step = 20; for (int i = 0; i != (delay + delay_step - 1) / delay_step; ++i) { if (handle_interface()) return false; if (skip_) break; disp_.delay(std::min<int>(delay_step, delay - i * delay_step)); } } ++fi_n; } return true; }
static int handle_rename(unsigned int ifindex, const char *ifname) { struct interface *ifp; TAILQ_FOREACH(ifp, ifaces, next) { if (ifp->index == ifindex && strcmp(ifp->name, ifname)) { handle_interface(-1, ifp->name); /* Let dev announce the interface for renaming */ if (!dev_listening()) handle_interface(1, ifname); return 1; } } return 0; }
void part_ui::wait_for_input() { LOG_NG << "ENTER part_ui()::wait_for_input()\n"; last_key_ = true; skip_ = true; while (!handle_interface()) {} }
int manage_link(int fd) { char *p, *e, *cp; char ifname[IF_NAMESIZE]; ssize_t bytes; struct rt_msghdr *rtm; struct if_announcemsghdr *ifan; struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct rt rt; struct sockaddr *sa, *rti_info[RTAX_MAX]; int len; #ifdef RTM_CHGADDR struct sockaddr_dl sdl; unsigned char *hwaddr; #endif for (;;) { if (ioctl(fd, FIONREAD, &len) == -1) return -1; if (link_buflen < len) { p = realloc(link_buf, len); if (p == NULL) return -1; link_buf = p; link_buflen = len; } bytes = read(fd, link_buf, link_buflen); if (bytes == -1) { if (errno == EAGAIN) return 0; if (errno == EINTR) continue; return -1; } e = link_buf + bytes; for (p = link_buf; p < e; p += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)(void *)p; switch(rtm->rtm_type) { #ifdef RTM_IFANNOUNCE case RTM_IFANNOUNCE: ifan = (struct if_announcemsghdr *)(void *)p; switch(ifan->ifan_what) { case IFAN_ARRIVAL: handle_interface(1, ifan->ifan_name); break; case IFAN_DEPARTURE: handle_interface(-1, ifan->ifan_name); break; } break; #endif case RTM_IFINFO: ifm = (struct if_msghdr *)(void *)p; memset(ifname, 0, sizeof(ifname)); if (if_indextoname(ifm->ifm_index, ifname)) handle_interface(0, ifname); break; case RTM_DELETE: if (!(rtm->rtm_addrs & RTA_DST) || !(rtm->rtm_addrs & RTA_GATEWAY) || !(rtm->rtm_addrs & RTA_NETMASK)) break; if (rtm->rtm_pid == getpid()) break; cp = (char *)(void *)(rtm + 1); sa = (struct sockaddr *)(void *)cp; if (sa->sa_family != AF_INET) break; get_addrs(rtm->rtm_addrs, cp, rti_info); rt.iface = NULL; rt.next = NULL; COPYOUT(rt.dest, rti_info[RTAX_DST]); COPYOUT(rt.net, rti_info[RTAX_NETMASK]); COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]); route_deleted(&rt); break; #ifdef RTM_CHGADDR case RTM_CHGADDR: /* FALLTHROUGH */ #endif case RTM_DELADDR: /* FALLTHROUGH */ case RTM_NEWADDR: ifam = (struct ifa_msghdr *)(void *)p; if (!if_indextoname(ifam->ifam_index, ifname)) break; cp = (char *)(void *)(ifam + 1); get_addrs(ifam->ifam_addrs, cp, rti_info); if (rti_info[RTAX_IFA] == NULL) break; switch (rti_info[RTAX_IFA]->sa_family) { #ifdef RTM_CHGADDR case AF_LINK: if (rtm->rtm_type != RTM_CHGADDR) break; memcpy(&sdl, rti_info[RTAX_IFA], rti_info[RTAX_IFA]->sa_len); hwaddr = xmalloc(sdl.sdl_alen); memcpy(hwaddr, LLADDR(&sdl), sdl.sdl_alen); handle_hwaddr(ifname, hwaddr, sdl.sdl_alen); break; #endif case AF_INET: case 255: /* FIXME: Why 255? */ COPYOUT(rt.dest, rti_info[RTAX_IFA]); COPYOUT(rt.net, rti_info[RTAX_NETMASK]); COPYOUT(rt.gate, rti_info[RTAX_BRD]); handle_ifa(rtm->rtm_type, ifname, &rt.dest, &rt.net, &rt.gate); break; } break; } } } }
void part_ui::render_story_box() { #ifdef SDL_GPU LOG_NG << "ENTER part_ui()::render_story_box()\n"; GPU_Target *target = get_render_target(); const std::string& storytxt = p_.text(); if(storytxt.empty()) { video_.flip(); wait_for_input(); return; } const part::BLOCK_LOCATION tbl = p_.story_text_location(); const int max_width = buttons_x_ - storybox_padding - text_x_; const int max_height = screen_area().h - storybox_padding; skip_ = false; last_key_ = true; font::ttext t; if(!t.set_text(p_.text(), true)) { ERR_NG << "Text: Invalid markup in '" << p_.text() << "' rendered as is.\n"; t.set_text(p_.text(), false); } t.set_font_style(font::ttext::STYLE_NORMAL) .set_font_size(storybox_font_size) .set_foreground_color(storybox_font_color) .set_maximum_width(max_width) .set_maximum_height(max_height, true); sdl::timage txttxt = t.render_as_texture(); if(txttxt.null()) { ERR_NG << "storyscreen text area rendering resulted in a null texture" << std::endl; return; } int fix_text_y = text_y_; if(fix_text_y + 2*(storybox_padding+1) + txttxt.height() > screen_area().h && tbl != part::BLOCK_TOP) { fix_text_y = (screen_area().h > txttxt.height() + 1) ? (std::max(0, screen_area().h - txttxt.height() - 2*(storybox_padding+1))) : (0); } int fix_text_h; switch(tbl) { case part::BLOCK_TOP: fix_text_h = std::max(txttxt.height() + 2*storybox_padding, screen_area().h/4); break; case part::BLOCK_MIDDLE: fix_text_h = std::max(txttxt.height() + 2*storybox_padding, screen_area().h/3); break; default: fix_text_h = screen_area().h - fix_text_y; break; } SDL_Rect update_area = sdl::create_rect(0 , fix_text_y , screen_area().w , fix_text_h); /* do */ { // this should kill the tiniest flickering caused // by the buttons being hidden and unhidden in this scope. update_locker locker(video_); next_button_.hide(); back_button_.hide(); play_button_.hide(); //TODO: blurring const SDL_Rect box = sdl::create_rect(0, fix_text_y, screen_area().w, fix_text_h); sdl::fill_rect(*target, box, storyshadow_r, storyshadow_g, storyshadow_b, storyshadow_a); render_story_box_borders(update_area); // no-op if LOW_MEM is defined next_button_.hide(false); back_button_.hide(false); play_button_.hide(false); } // Time to do some f*****g visual effect. const int scan_height = 1, scan_width = txttxt.width(); SDL_Rect scan = sdl::create_rect(0, 0, scan_width, scan_height); SDL_Rect dstrect = sdl::create_rect(text_x_, 0, scan_width, scan_height); bool scan_finished = false; while(true) { scan_finished = scan.y >= txttxt.base_height(); if (!scan_finished) { dstrect.y = fix_text_y + scan.y + storybox_padding; txttxt.set_clip(scan); video_.draw_texture(txttxt, dstrect.x, dstrect.y); video_.flip(); ++scan.y; } else skip_ = true; if (handle_interface()) break; if (!skip_ || scan_finished) { disp_.delay(20); } } const SDL_Rect rect = sdl::create_rect(0, 0, video_.getx(), video_.gety()); sdl::fill_rect(*target, rect, 0, 0, 0, 255); #else LOG_NG << "ENTER part_ui()::render_story_box()\n"; const std::string& storytxt = p_.text(); if(storytxt.empty()) { update_whole_screen(); wait_for_input(); return; } const part::BLOCK_LOCATION tbl = p_.story_text_location(); const int max_width = buttons_x_ - storybox_padding - text_x_; const int max_height = screen_area().h - storybox_padding; skip_ = false; last_key_ = true; font::ttext t; if(!t.set_text(p_.text(), true)) { ERR_NG << "Text: Invalid markup in '" << p_.text() << "' rendered as is.\n"; t.set_text(p_.text(), false); } t.set_font_style(font::ttext::STYLE_NORMAL) .set_font_size(storybox_font_size) .set_foreground_color(storybox_font_color) .set_maximum_width(max_width) .set_maximum_height(max_height, true); surface txtsurf = t.render(); if(txtsurf.null()) { ERR_NG << "storyscreen text area rendering resulted in a null surface" << std::endl; return; } int fix_text_y = text_y_; if(fix_text_y + 2*(storybox_padding+1) + txtsurf->h > screen_area().h && tbl != part::BLOCK_TOP) { fix_text_y = (screen_area().h > txtsurf->h + 1) ? (std::max(0, screen_area().h - txtsurf->h - 2*(storybox_padding+1))) : (0); } int fix_text_h; switch(tbl) { case part::BLOCK_TOP: fix_text_h = std::max(txtsurf->h + 2*storybox_padding, screen_area().h/4); break; case part::BLOCK_MIDDLE: fix_text_h = std::max(txtsurf->h + 2*storybox_padding, screen_area().h/3); break; default: fix_text_h = screen_area().h - fix_text_y; break; } SDL_Rect update_area = sdl::create_rect(0 , fix_text_y , screen_area().w , fix_text_h); /* do */ { // this should kill the tiniest flickering caused // by the buttons being hidden and unhidden in this scope. update_locker locker(video_); next_button_.hide(); back_button_.hide(); play_button_.hide(); #ifndef LOW_MEM blur_area(video_, fix_text_y, fix_text_h); #endif sdl::draw_solid_tinted_rectangle( 0, fix_text_y, screen_area().w, fix_text_h, storyshadow_r, storyshadow_g, storyshadow_b, storyshadow_opacity, video_.getSurface() ); render_story_box_borders(update_area); // no-op if LOW_MEM is defined next_button_.hide(false); back_button_.hide(false); play_button_.hide(false); } if(imgs_.empty()) { update_whole_screen(); } else if(update_area.h > 0) { update_rect(update_area); } // Time to do some f*****g visual effect. const int scan_height = 1, scan_width = txtsurf->w; SDL_Rect scan = sdl::create_rect(0, 0, scan_width, scan_height); SDL_Rect dstrect = sdl::create_rect(text_x_, 0, scan_width, scan_height); surface scan_dst = video_.getSurface(); bool scan_finished = false; while(true) { scan_finished = scan.y >= txtsurf->h; if (!scan_finished) { //dstrect.x = text_x_; dstrect.y = fix_text_y + scan.y + storybox_padding; // NOTE: ::blit_surface() screws up with antialiasing and hinting when // on backgroundless (e.g. black) screens; ttext::draw() // uses it nonetheless, no idea why... // Here we'll use CVideo::blit_surface() instead. video_.blit_surface(dstrect.x, dstrect.y, txtsurf, &scan); update_rect(dstrect); ++scan.y; } else skip_ = true; if (handle_interface()) break; if (!skip_ || scan_finished) { disp_.delay(20); } } sdl::draw_solid_tinted_rectangle( 0, 0, video_.getx(), video_.gety(), 0, 0, 0, 1.0, video_.getSurface() ); #endif }
int manage_link(int fd) { char *p, *e, *cp; char ifname[IF_NAMESIZE]; ssize_t bytes; struct rt_msghdr *rtm; struct if_announcemsghdr *ifan; struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct sockaddr *sa, *rti_info[RTAX_MAX]; int len; struct sockaddr_dl sdl; #ifdef INET struct rt rt; #endif #if defined(INET6) && !defined(LISTEN_DAD) struct in6_addr ia6; struct sockaddr_in6 *sin6; int ifa_flags; #endif for (;;) { if (ioctl(fd, FIONREAD, &len) == -1) return -1; if (link_buflen < len) { p = realloc(link_buf, len); if (p == NULL) return -1; link_buf = p; link_buflen = len; } bytes = read(fd, link_buf, link_buflen); if (bytes == -1) { if (errno == EAGAIN) return 0; if (errno == EINTR) continue; return -1; } e = link_buf + bytes; for (p = link_buf; p < e; p += rtm->rtm_msglen) { rtm = (struct rt_msghdr *)(void *)p; // Ignore messages generated by us if (rtm->rtm_pid == getpid()) break; switch(rtm->rtm_type) { #ifdef RTM_IFANNOUNCE case RTM_IFANNOUNCE: ifan = (struct if_announcemsghdr *)(void *)p; switch(ifan->ifan_what) { case IFAN_ARRIVAL: handle_interface(1, ifan->ifan_name); break; case IFAN_DEPARTURE: handle_interface(-1, ifan->ifan_name); break; } break; #endif case RTM_IFINFO: ifm = (struct if_msghdr *)(void *)p; memset(ifname, 0, sizeof(ifname)); if (!(if_indextoname(ifm->ifm_index, ifname))) break; switch (ifm->ifm_data.ifi_link_state) { case LINK_STATE_DOWN: len = LINK_DOWN; break; case LINK_STATE_UP: len = LINK_UP; break; default: /* handle_carrier will re-load * the interface flags and check for * IFF_RUNNING as some drivers that * don't handle link state also don't * set IFF_RUNNING when this routing * message is generated. * As such, it is a race ...*/ len = LINK_UNKNOWN; break; } handle_carrier(len, ifm->ifm_flags, ifname); break; case RTM_DELETE: if (~rtm->rtm_addrs & (RTA_DST | RTA_GATEWAY | RTA_NETMASK)) break; cp = (char *)(void *)(rtm + 1); sa = (struct sockaddr *)(void *)cp; if (sa->sa_family != AF_INET) break; #ifdef INET get_addrs(rtm->rtm_addrs, cp, rti_info); memset(&rt, 0, sizeof(rt)); rt.iface = NULL; COPYOUT(rt.dest, rti_info[RTAX_DST]); COPYOUT(rt.net, rti_info[RTAX_NETMASK]); COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]); ipv4_routedeleted(&rt); #endif break; #ifdef RTM_CHGADDR case RTM_CHGADDR: /* FALLTHROUGH */ #endif case RTM_DELADDR: /* FALLTHROUGH */ case RTM_NEWADDR: ifam = (struct ifa_msghdr *)(void *)p; if (!if_indextoname(ifam->ifam_index, ifname)) break; cp = (char *)(void *)(ifam + 1); get_addrs(ifam->ifam_addrs, cp, rti_info); if (rti_info[RTAX_IFA] == NULL) break; switch (rti_info[RTAX_IFA]->sa_family) { case AF_LINK: #ifdef RTM_CHGADDR if (rtm->rtm_type != RTM_CHGADDR) break; #else if (rtm->rtm_type != RTM_NEWADDR) break; #endif memcpy(&sdl, rti_info[RTAX_IFA], rti_info[RTAX_IFA]->sa_len); handle_hwaddr(ifname, (const unsigned char*)CLLADDR(&sdl), sdl.sdl_alen); break; #ifdef INET case AF_INET: case 255: /* FIXME: Why 255? */ COPYOUT(rt.dest, rti_info[RTAX_IFA]); COPYOUT(rt.net, rti_info[RTAX_NETMASK]); COPYOUT(rt.gate, rti_info[RTAX_BRD]); ipv4_handleifa(rtm->rtm_type, NULL, ifname, &rt.dest, &rt.net, &rt.gate); break; #endif #if defined(INET6) && !defined(LISTEN_DAD) case AF_INET6: sin6 = (struct sockaddr_in6*)(void *) rti_info[RTAX_IFA]; memcpy(ia6.s6_addr, sin6->sin6_addr.s6_addr, sizeof(ia6.s6_addr)); if (rtm->rtm_type == RTM_NEWADDR) { ifa_flags = in6_addr_flags( ifname, &ia6); if (ifa_flags == -1) break; } else ifa_flags = 0; ipv6_handleifa(rtm->rtm_type, NULL, ifname, &ia6, ifa_flags); break; #endif } break; } } } }
bool part_ui::render_floating_images() { #ifdef SDL_GPU skip_ = false; last_key_ = true; size_t fi_n = 0; BOOST_FOREACH(floating_image::render_input& ri, imgs_) { const floating_image& fi = p_.get_floating_images()[fi_n]; if(!ri.image.null()) { ri.image.draw(video_, ri.rect.x, ri.rect.y); video_.flip(); } if (!skip_) { int delay = fi.display_delay(), delay_step = 20; for (int i = 0; i != (delay + delay_step - 1) / delay_step; ++i) { if (handle_interface()) return false; if (skip_) break; CVideo::delay(std::min<int>(delay_step, delay - i * delay_step)); } } ++fi_n; } return true; #else events::raise_draw_event(); skip_ = false; last_key_ = true; size_t fi_n = 0; BOOST_FOREACH(floating_image::render_input& ri, imgs_) { const floating_image& fi = p_.get_floating_images()[fi_n]; if(!ri.image.null()) { render_background(); for (size_t i = 0; i <= fi_n; i++) { floating_image::render_input& old_ri = imgs_[i]; sdl_blit(old_ri.image, NULL, video_.getSurface(), &old_ri.rect); update_rect(old_ri.rect); } } if (!skip_) { int delay = fi.display_delay(), delay_step = 20; for (int i = 0; i != (delay + delay_step - 1) / delay_step; ++i) { if (handle_interface()) return false; if (skip_) break; CVideo::delay(std::min<int>(delay_step, delay - i * delay_step)); } } ++fi_n; } return true; #endif }
static int link_netlink(struct nlmsghdr *nlm) { int len; struct rtattr *rta, *hwaddr; struct ifinfomsg *ifi; char ifn[IF_NAMESIZE + 1]; struct interface *ifp; len = link_route(nlm); if (len != 0) return len; len = link_addr(nlm); if (len != 0) return len; if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK) return 0; len = nlm->nlmsg_len - sizeof(*nlm); if ((size_t)len < sizeof(*ifi)) { errno = EBADMSG; return -1; } ifi = NLMSG_DATA(nlm); if (ifi->ifi_flags & IFF_LOOPBACK) return 1; rta = (struct rtattr *)(void *)((char *)ifi +NLMSG_ALIGN(sizeof(*ifi))); len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); *ifn = '\0'; hwaddr = NULL; while (RTA_OK(rta, len)) { switch (rta->rta_type) { case IFLA_WIRELESS: /* Ignore wireless messages */ if (nlm->nlmsg_type == RTM_NEWLINK && ifi->ifi_change == 0) return 1; break; case IFLA_IFNAME: strlcpy(ifn, RTA_DATA(rta), sizeof(ifn)); break; case IFLA_ADDRESS: hwaddr = rta; break; } rta = RTA_NEXT(rta, len); } if (nlm->nlmsg_type == RTM_DELLINK) { handle_interface(-1, ifn); return 1; } /* Virtual interfaces may not get a valid hardware address * at this point. * To trigger a valid hardware address pickup we need to pretend * that that don't exist until they have one. */ if (ifi->ifi_flags & IFF_MASTER && !hwaddr) { handle_interface(-1, ifn); return 1; } /* Check for interface name change */ if (handle_rename(ifi->ifi_index, ifn)) return 1; /* Check for a new interface */ ifp = find_interface(ifn); if (ifp == NULL) { /* If are listening to a dev manager, let that announce * the interface rather than the kernel. */ if (dev_listening() < 1) handle_interface(1, ifn); return 1; } /* Re-read hardware address and friends */ if (!(ifi->ifi_flags & IFF_UP) && hwaddr) { len = l2addr_len(ifi->ifi_type); if (hwaddr->rta_len == RTA_LENGTH(len)) handle_hwaddr(ifn, RTA_DATA(hwaddr), len); } handle_carrier(ifi->ifi_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN, ifi->ifi_flags, ifn); return 1; }