Пример #1
0
int sd_icmp6_router_solicitation_start(sd_icmp6_nd *nd) {
        int r;

        assert(nd);
        assert(nd->event);

        if (nd->state != ICMP6_NEIGHBOR_DISCOVERY_IDLE)
                return -EINVAL;

        if (nd->index < 1)
                return -EINVAL;

        r = dhcp_network_icmp6_bind_router_solicitation(nd->index);
        if (r < 0)
                return r;

        nd->fd = r;

        r = sd_event_add_io(nd->event, &nd->recv, nd->fd, EPOLLIN,
                            icmp6_router_advertisment_recv, nd);
        if (r < 0)
                goto error;

        r = sd_event_source_set_priority(nd->recv, nd->event_priority);
        if (r < 0)
                goto error;

        r = sd_event_source_set_description(nd->recv, "icmp6-receive-message");
        if (r < 0)
                goto error;

        r = sd_event_add_time(nd->event, &nd->timeout, clock_boottime_or_monotonic(),
                              0, 0, icmp6_router_solicitation_timeout, nd);
        if (r < 0)
                goto error;

        r = sd_event_source_set_priority(nd->timeout, nd->event_priority);
        if (r < 0)
                goto error;

        r = sd_event_source_set_description(nd->timeout, "icmp6-timeout");
error:
        if (r < 0)
                icmp6_nd_init(nd);
        else
                log_icmp6_nd(client, "Start Router Solicitation");

        return r;
}
Пример #2
0
static int scope_arm_timer(Scope *s, usec_t usec) {
        int r;

        assert(s);

        if (s->timer_event_source) {
                r = sd_event_source_set_time(s->timer_event_source, usec);
                if (r < 0)
                        return r;

                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
        }

        if (usec == USEC_INFINITY)
                return 0;

        r = sd_event_add_time(
                        UNIT(s)->manager->event,
                        &s->timer_event_source,
                        CLOCK_MONOTONIC,
                        usec, 0,
                        scope_dispatch_timer, s);
        if (r < 0)
                return r;

        (void) sd_event_source_set_description(s->timer_event_source, "scope-timer");

        return 0;
}
Пример #3
0
static int automount_coldplug(Unit *u) {
        Automount *a = AUTOMOUNT(u);
        int r;

        assert(a);
        assert(a->state == AUTOMOUNT_DEAD);

        if (a->deserialized_state != a->state) {

                r = open_dev_autofs(u->manager);
                if (r < 0)
                        return r;

                if (a->deserialized_state == AUTOMOUNT_WAITING ||
                    a->deserialized_state == AUTOMOUNT_RUNNING) {
                        assert(a->pipe_fd >= 0);

                        r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
                        if (r < 0)
                                return r;

                        (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
                }

                automount_set_state(a, a->deserialized_state);
        }

        return 0;
}
Пример #4
0
static int automount_start_expire(Automount *a) {
        int r;
        usec_t timeout;

        assert(a);

        if (a->timeout_idle_usec == 0)
                return 0;

        timeout = now(CLOCK_MONOTONIC) + MAX(a->timeout_idle_usec/3, USEC_PER_SEC);

        if (a->expire_event_source) {
                r = sd_event_source_set_time(a->expire_event_source, timeout);
                if (r < 0)
                        return r;

                return sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_ONESHOT);
        }

        r = sd_event_add_time(
                        UNIT(a)->manager->event,
                        &a->expire_event_source,
                        CLOCK_MONOTONIC, timeout, 0,
                        automount_dispatch_expire, a);
        if (r < 0)
                return r;

        (void) sd_event_source_set_description(a->expire_event_source, "automount-expire");

        return 0;
}
Пример #5
0
static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata) {
        CurlGlue *g = userdata;
        usec_t usec;

        assert(curl);
        assert(g);

        if (timeout_ms < 0) {
                if (g->timer) {
                        if (sd_event_source_set_enabled(g->timer, SD_EVENT_OFF) < 0)
                                return -1;
                }

                return 0;
        }

        usec = now(clock_boottime_or_monotonic()) + (usec_t) timeout_ms * USEC_PER_MSEC + USEC_PER_MSEC - 1;

        if (g->timer) {
                if (sd_event_source_set_time(g->timer, usec) < 0)
                        return -1;

                if (sd_event_source_set_enabled(g->timer, SD_EVENT_ONESHOT) < 0)
                        return -1;
        } else {
                if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0)
                        return -1;

                (void) sd_event_source_set_description(g->timer, "curl-timer");
        }

        return 0;
}
Пример #6
0
_public_ int sd_lldp_start(sd_lldp *lldp) {
        int r;

        assert_return(lldp, -EINVAL);

        if (lldp->fd >= 0)
                return 0;

        assert(!lldp->io_event_source);

        lldp->fd = lldp_network_bind_raw_socket(lldp->ifindex);
        if (lldp->fd < 0)
                return lldp->fd;

        if (lldp->event) {
                r = sd_event_add_io(lldp->event, &lldp->io_event_source, lldp->fd, EPOLLIN, lldp_receive_datagram, lldp);
                if (r < 0)
                        goto fail;

                r = sd_event_source_set_priority(lldp->io_event_source, lldp->event_priority);
                if (r < 0)
                        goto fail;

                (void) sd_event_source_set_description(lldp->io_event_source, "lldp-io");
        }

        return 1;

fail:
        lldp->io_event_source = sd_event_source_unref(lldp->io_event_source);
        lldp->fd = safe_close(lldp->fd);

        return r;
}
Пример #7
0
static int busname_watch_fd(BusName *n) {
        int r;

        assert(n);

        if (n->starter_fd < 0)
                return 0;

        if (n->starter_event_source) {
                r = sd_event_source_set_enabled(n->starter_event_source, SD_EVENT_ON);
                if (r < 0)
                        goto fail;
        } else {
                r = sd_event_add_io(UNIT(n)->manager->event, &n->starter_event_source, n->starter_fd, EPOLLIN, busname_dispatch_io, n);
                if (r < 0)
                        goto fail;

                (void) sd_event_source_set_description(n->starter_event_source, "busname-starter");
        }

        return 0;

fail:
        log_unit_warning_errno(UNIT(n), r, "Failed to watch starter fd: %m");
        busname_unwatch_fd(n);
        return r;
}
Пример #8
0
static int scope_arm_timer(Scope *s) {
        int r;

        assert(s);

        if (s->timeout_stop_usec <= 0) {
                s->timer_event_source = sd_event_source_unref(s->timer_event_source);
                return 0;
        }

        if (s->timer_event_source) {
                r = sd_event_source_set_time(s->timer_event_source, now(CLOCK_MONOTONIC) + s->timeout_stop_usec);
                if (r < 0)
                        return r;

                return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
        }

        r = sd_event_add_time(
                        UNIT(s)->manager->event,
                        &s->timer_event_source,
                        CLOCK_MONOTONIC,
                        now(CLOCK_MONOTONIC) + s->timeout_stop_usec, 0,
                        scope_dispatch_timer, s);
        if (r < 0)
                return r;

        (void) sd_event_source_set_description(s->timer_event_source, "scope-timer");

        return 0;
}
Пример #9
0
static int ipv4acd_set_next_wakeup(sd_ipv4acd *acd, usec_t usec, usec_t random_usec) {
        _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
        usec_t next_timeout, time_now;
        int r;

        assert(acd);

        next_timeout = usec;

        if (random_usec > 0)
                next_timeout += (usec_t) random_u64() % random_usec;

        assert_se(sd_event_now(acd->event, clock_boottime_or_monotonic(), &time_now) >= 0);

        r = sd_event_add_time(acd->event, &timer, clock_boottime_or_monotonic(), time_now + next_timeout, 0, ipv4acd_on_timeout, acd);
        if (r < 0)
                return r;

        r = sd_event_source_set_priority(timer, acd->event_priority);
        if (r < 0)
                return r;

        (void) sd_event_source_set_description(timer, "ipv4acd-timer");

        sd_event_source_unref(acd->timer_event_source);
        acd->timer_event_source = timer;
        timer = NULL;

        return 0;
}
Пример #10
0
static int busname_arm_timer(BusName *n, usec_t usec) {
        int r;

        assert(n);

        if (n->timer_event_source) {
                r = sd_event_source_set_time(n->timer_event_source, usec);
                if (r < 0)
                        return r;

                return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
        }

        if (usec == USEC_INFINITY)
                return 0;

        r = sd_event_add_time(
                        UNIT(n)->manager->event,
                        &n->timer_event_source,
                        CLOCK_MONOTONIC,
                        usec, 0,
                        busname_dispatch_timer, n);
        if (r < 0)
                return r;

        (void) sd_event_source_set_description(n->timer_event_source, "busname-timer");

        return 0;
}
Пример #11
0
static int busname_arm_timer(BusName *n) {
        int r;

        assert(n);

        if (n->timeout_usec <= 0) {
                n->timer_event_source = sd_event_source_unref(n->timer_event_source);
                return 0;
        }

        if (n->timer_event_source) {
                r = sd_event_source_set_time(n->timer_event_source, now(CLOCK_MONOTONIC) + n->timeout_usec);
                if (r < 0)
                        return r;

                return sd_event_source_set_enabled(n->timer_event_source, SD_EVENT_ONESHOT);
        }

        r =  sd_event_add_time(
                        UNIT(n)->manager->event,
                        &n->timer_event_source,
                        CLOCK_MONOTONIC,
                        now(CLOCK_MONOTONIC) + n->timeout_usec, 0,
                        busname_dispatch_timer, n);
        if (r < 0)
                return r;

        (void) sd_event_source_set_description(n->timer_event_source, "busname-timer");

        return 0;
}
Пример #12
0
static int automount_coldplug(Unit *u) {
        Automount *a = AUTOMOUNT(u);
        int r;

        assert(a);
        assert(a->state == AUTOMOUNT_DEAD);

        if (a->deserialized_state != a->state) {

                r = open_dev_autofs(u->manager);
                if (r < 0)
                        return r;

                if (a->deserialized_state == AUTOMOUNT_WAITING ||
                    a->deserialized_state == AUTOMOUNT_RUNNING) {
                        assert(a->pipe_fd >= 0);

                        r = sd_event_add_io(u->manager->event, &a->pipe_event_source, a->pipe_fd, EPOLLIN, automount_dispatch_io, u);
                        if (r < 0)
                                return r;

                        (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");
                        if (a->deserialized_state == AUTOMOUNT_RUNNING) {
                                r = automount_start_expire(a);
                                if (r < 0)
                                        log_unit_warning_errno(UNIT(a), r, "Failed to start expiration timer, ignoring: %m");
                        }
                }

                automount_set_state(a, a->deserialized_state);
        }

        return 0;
}
Пример #13
0
int link_lldp_emit_start(Link *link) {
        usec_t next;
        int r;

        assert(link);

        if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) {
                link_lldp_emit_stop(link);
                return 0;
        }

        /* Starts the LLDP transmission in "fast" mode. If it is already started, turns "fast" mode back on again. */

        link->lldp_tx_fast = LLDP_TX_FAST_INIT;

        next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC),
                     (usec_t) random_u64() % LLDP_JITTER_USEC);

        if (link->lldp_emit_event_source) {
                usec_t old;

                /* Lower the timeout, maybe */
                r = sd_event_source_get_time(link->lldp_emit_event_source, &old);
                if (r < 0)
                        return r;

                if (old <= next)
                        return 0;

                return sd_event_source_set_time(link->lldp_emit_event_source, next);
        } else {
                r = sd_event_add_time(
                                link->manager->event,
                                &link->lldp_emit_event_source,
                                clock_boottime_or_monotonic(),
                                next,
                                0,
                                on_lldp_timer,
                                link);
                if (r < 0)
                        return r;

                (void) sd_event_source_set_description(link->lldp_emit_event_source, "lldp-tx");
        }

        return 0;
}
Пример #14
0
int sd_ipv4acd_start(sd_ipv4acd *ll) {
        int r;

        assert_return(ll, -EINVAL);
        assert_return(ll->event, -EINVAL);
        assert_return(ll->index > 0, -EINVAL);
        assert_return(ll->address != 0, -EINVAL);
        assert_return(!ether_addr_is_nul(&ll->mac_addr), -EINVAL);
        assert_return(ll->state == IPV4ACD_STATE_INIT, -EBUSY);

        ll->defend_window = 0;

        r = arp_network_bind_raw_socket(ll->index, ll->address, &ll->mac_addr);
        if (r < 0)
                goto out;

        ll->fd = safe_close(ll->fd);
        ll->fd = r;

        r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
                            EPOLLIN, ipv4acd_on_packet, ll);
        if (r < 0)
                goto out;

        r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
        if (r < 0)
                goto out;

        r = sd_event_source_set_description(ll->receive_message, "ipv4acd-receive-message");
        if (r < 0)
                goto out;

        r = ipv4acd_set_next_wakeup(ll, 0, 0);
        if (r < 0)
                goto out;
out:
        if (r < 0) {
                ipv4acd_stop(ll);
                return r;
        }

        return 0;
}
Пример #15
0
int sd_ipv4acd_start(sd_ipv4acd *acd) {
        int r;

        assert_return(acd, -EINVAL);
        assert_return(acd->event, -EINVAL);
        assert_return(acd->ifindex > 0, -EINVAL);
        assert_return(acd->address != 0, -EINVAL);
        assert_return(!ether_addr_is_null(&acd->mac_addr), -EINVAL);
        assert_return(acd->state == IPV4ACD_STATE_INIT, -EBUSY);

        r = arp_network_bind_raw_socket(acd->ifindex, acd->address, &acd->mac_addr);
        if (r < 0)
                return r;

        safe_close(acd->fd);
        acd->fd = r;
        acd->defend_window = 0;
        acd->n_conflict = 0;

        r = sd_event_add_io(acd->event, &acd->receive_message_event_source, acd->fd, EPOLLIN, ipv4acd_on_packet, acd);
        if (r < 0)
                goto fail;

        r = sd_event_source_set_priority(acd->receive_message_event_source, acd->event_priority);
        if (r < 0)
                goto fail;

        (void) sd_event_source_set_description(acd->receive_message_event_source, "ipv4acd-receive-message");

        r = ipv4acd_set_next_wakeup(acd, 0, 0);
        if (r < 0)
                goto fail;

        ipv4acd_set_state(acd, IPV4ACD_STATE_STARTED, true);
        return 0;

fail:
        ipv4acd_reset(acd);
        return r;
}
Пример #16
0
static int lldp_start_timer(sd_lldp *lldp, sd_lldp_neighbor *neighbor) {
        sd_lldp_neighbor *n;
        int r;

        assert(lldp);

        if (neighbor)
                lldp_neighbor_start_ttl(neighbor);

        n = prioq_peek(lldp->neighbor_by_expiry);
        if (!n) {

                if (lldp->timer_event_source)
                        return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_OFF);

                return 0;
        }

        if (lldp->timer_event_source) {
                r = sd_event_source_set_time(lldp->timer_event_source, n->until);
                if (r < 0)
                        return r;

                return sd_event_source_set_enabled(lldp->timer_event_source, SD_EVENT_ONESHOT);
        }

        if (!lldp->event)
                return 0;

        r = sd_event_add_time(lldp->event, &lldp->timer_event_source, clock_boottime_or_monotonic(), n->until, 0, on_timer_event, lldp);
        if (r < 0)
                return r;

        r = sd_event_source_set_priority(lldp->timer_event_source, lldp->event_priority);
        if (r < 0)
                return r;

        (void) sd_event_source_set_description(lldp->timer_event_source, "lldp-timer");
        return 0;
}
Пример #17
0
int lldp_port_start(lldp_port *p) {
        int r;

        assert_return(p, -EINVAL);

        r = lldp_network_bind_raw_socket(p->ifindex);
        if (r < 0)
                return r;

        p->rawfd = r;

        r = sd_event_add_io(p->event, &p->lldp_port_rx,
                            p->rawfd, EPOLLIN, lldp_receive_packet, p);
        if (r < 0) {
                log_debug_errno(r, "Failed to allocate event source: %m");
                goto fail;
        }

        r = sd_event_source_set_priority(p->lldp_port_rx, p->event_priority);
        if (r < 0) {
                log_debug_errno(r, "Failed to set event priority: %m");
                goto fail;
        }

        r = sd_event_source_set_description(p->lldp_port_rx, "lldp-port-rx");
        if (r < 0) {
                log_debug_errno(r, "Failed to set event name: %m");
                goto fail;
        }

        return 0;

fail:
        lldp_port_stop(p);

        return r;
}
Пример #18
0
static int ipv4acd_set_next_wakeup(sd_ipv4acd *ll, int sec, int random_sec) {
        _cleanup_(sd_event_source_unrefp) sd_event_source *timer = NULL;
        usec_t next_timeout;
        usec_t time_now;
        int r;

        assert(sec >= 0);
        assert(random_sec >= 0);
        assert(ll);

        next_timeout = sec * USEC_PER_SEC;

        if (random_sec)
                next_timeout += random_u32() % (random_sec * USEC_PER_SEC);

        assert_se(sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now) >= 0);

        r = sd_event_add_time(ll->event, &timer, clock_boottime_or_monotonic(),
                              time_now + next_timeout, 0, ipv4acd_on_timeout, ll);
        if (r < 0)
                return r;

        r = sd_event_source_set_priority(timer, ll->event_priority);
        if (r < 0)
                return r;

        r = sd_event_source_set_description(timer, "ipv4acd-timer");
        if (r < 0)
                return r;

        ll->timer = sd_event_source_unref(ll->timer);
        ll->timer = timer;
        timer = NULL;

        return 0;
}
Пример #19
0
static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, void *userdata, void *socketp) {
        sd_event_source *io;
        CurlGlue *g = userdata;
        uint32_t events = 0;
        int r;

        assert(curl);
        assert(g);

        io = hashmap_get(g->ios, FD_TO_PTR(s));

        if (action == CURL_POLL_REMOVE) {
                if (io) {
                        int fd;

                        fd = sd_event_source_get_io_fd(io);
                        assert(fd >= 0);

                        sd_event_source_set_enabled(io, SD_EVENT_OFF);
                        sd_event_source_unref(io);

                        hashmap_remove(g->ios, FD_TO_PTR(s));
                        hashmap_remove(g->translate_fds, FD_TO_PTR(fd));

                        safe_close(fd);
                }

                return 0;
        }

        r = hashmap_ensure_allocated(&g->ios, &trivial_hash_ops);
        if (r < 0) {
                log_oom();
                return -1;
        }

        r = hashmap_ensure_allocated(&g->translate_fds, &trivial_hash_ops);
        if (r < 0) {
                log_oom();
                return -1;
        }

        if (action == CURL_POLL_IN)
                events = EPOLLIN;
        else if (action == CURL_POLL_OUT)
                events = EPOLLOUT;
        else if (action == CURL_POLL_INOUT)
                events = EPOLLIN|EPOLLOUT;

        if (io) {
                if (sd_event_source_set_io_events(io, events) < 0)
                        return -1;

                if (sd_event_source_set_enabled(io, SD_EVENT_ON) < 0)
                        return -1;
        } else {
                _cleanup_close_ int fd = -1;

                /* When curl needs to remove an fd from us it closes
                 * the fd first, and only then calls into us. This is
                 * nasty, since we cannot pass the fd on to epoll()
                 * anymore. Hence, duplicate the fds here, and keep a
                 * copy for epoll which we control after use. */

                fd = fcntl(s, F_DUPFD_CLOEXEC, 3);
                if (fd < 0)
                        return -1;

                if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0)
                        return -1;

                (void) sd_event_source_set_description(io, "curl-io");

                r = hashmap_put(g->ios, FD_TO_PTR(s), io);
                if (r < 0) {
                        log_oom();
                        sd_event_source_unref(io);
                        return -1;
                }

                r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
                if (r < 0) {
                        log_oom();
                        hashmap_remove(g->ios, FD_TO_PTR(s));
                        sd_event_source_unref(io);
                        return -1;
                }

                fd = -1;
        }

        return 0;
}
Пример #20
0
static int icmp6_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
                                             void *userdata)
{
        sd_icmp6_nd *nd = userdata;
        uint64_t time_now, next_timeout;
        struct ether_addr unset = { };
        struct ether_addr *addr = NULL;
        int r;

        assert(s);
        assert(nd);
        assert(nd->event);

        nd->timeout = sd_event_source_unref(nd->timeout);

        if (nd->nd_sent >= ICMP6_MAX_ROUTER_SOLICITATIONS) {
                icmp6_nd_notify(nd, ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT);
                nd->state = ICMP6_ROUTER_ADVERTISMENT_LISTEN;
        } else {
                if (memcmp(&nd->mac_addr, &unset, sizeof(struct ether_addr)))
                        addr = &nd->mac_addr;

                r = dhcp_network_icmp6_send_router_solicitation(nd->fd, addr);
                if (r < 0)
                        log_icmp6_nd(nd, "Error sending Router Solicitation");
                else {
                        nd->state = ICMP6_ROUTER_SOLICITATION_SENT;
                        log_icmp6_nd(nd, "Sent Router Solicitation");
                }

                nd->nd_sent++;

                r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
                if (r < 0) {
                        icmp6_nd_notify(nd, r);
                        return 0;
                }

                next_timeout = time_now + ICMP6_ROUTER_SOLICITATION_INTERVAL;

                r = sd_event_add_time(nd->event, &nd->timeout, clock_boottime_or_monotonic(),
                                      next_timeout, 0,
                                      icmp6_router_solicitation_timeout, nd);
                if (r < 0) {
                        icmp6_nd_notify(nd, r);
                        return 0;
                }

                r = sd_event_source_set_priority(nd->timeout,
                                                 nd->event_priority);
                if (r < 0) {
                        icmp6_nd_notify(nd, r);
                        return 0;
                }

                r = sd_event_source_set_description(nd->timeout, "icmp6-timeout");
                if (r < 0) {
                        icmp6_nd_notify(nd, r);
                        return 0;
                }
        }

        return 0;
}
Пример #21
0
int sd_ipv4ll_start (sd_ipv4ll *ll) {
    int r;

    assert_return(ll, -EINVAL);
    assert_return(ll->event, -EINVAL);
    assert_return(ll->index > 0, -EINVAL);
    assert_return(IN_SET(ll->state, IPV4LL_STATE_INIT,
                         IPV4LL_STATE_STOPPED), -EBUSY);

    ll->state = IPV4LL_STATE_INIT;

    r = arp_network_bind_raw_socket(ll->index, &ll->link);

    if (r < 0)
        goto out;

    ll->fd = r;
    ll->conflict = 0;
    ll->defend_window = 0;
    ll->claimed_address = 0;

    if (!ll->random_data) {
        uint8_t seed[8];

        /* Fallback to mac */
        siphash24(seed, &ll->mac_addr.ether_addr_octet,
                  ETH_ALEN, HASH_KEY.bytes);

        r = sd_ipv4ll_set_address_seed(ll, seed);
        if (r < 0)
            goto out;
    }

    if (ll->address == 0) {
        r = ipv4ll_pick_address(ll, &ll->address);
        if (r < 0)
            goto out;
    }

    ipv4ll_set_state (ll, IPV4LL_STATE_INIT, 1);

    r = sd_event_add_io(ll->event, &ll->receive_message, ll->fd,
                        EPOLLIN, ipv4ll_receive_message, ll);
    if (r < 0)
        goto out;

    r = sd_event_source_set_priority(ll->receive_message, ll->event_priority);
    if (r < 0)
        goto out;

    r = sd_event_source_set_description(ll->receive_message, "ipv4ll-receive-message");
    if (r < 0)
        goto out;

    r = sd_event_add_time(ll->event,
                          &ll->timer,
                          clock_boottime_or_monotonic(),
                          now(clock_boottime_or_monotonic()), 0,
                          ipv4ll_timer, ll);

    if (r < 0)
        goto out;

    r = sd_event_source_set_priority(ll->timer, ll->event_priority);
    if (r < 0)
        goto out;

    r = sd_event_source_set_description(ll->timer, "ipv4ll-timer");
out:
    if (r < 0)
        ipv4ll_stop(ll, IPV4LL_EVENT_STOP);

    return 0;
}
Пример #22
0
static void ipv4ll_run_state_machine(sd_ipv4ll *ll, IPv4LLTrigger trigger, void *trigger_data) {
    struct ether_arp out_packet;
    int out_packet_ready = 0;
    int r = 0;

    assert(ll);
    assert(trigger < _IPV4LL_TRIGGER_MAX);

    if (ll->state == IPV4LL_STATE_INIT) {

        log_ipv4ll(ll, "PROBE");
        ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_PROBE, 1);
        ipv4ll_set_next_wakeup(ll, 0, PROBE_WAIT);

    } else if ((ll->state == IPV4LL_STATE_WAITING_PROBE && trigger == IPV4LL_TRIGGER_TIMEOUT) ||
               (ll->state == IPV4LL_STATE_PROBING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration < PROBE_NUM-2)) {

        /* Send a probe */
        arp_packet_probe(&out_packet, ll->address, &ll->mac_addr);
        out_packet_ready = 1;
        ipv4ll_set_state(ll, IPV4LL_STATE_PROBING, 0);

        ipv4ll_set_next_wakeup(ll, PROBE_MIN, (PROBE_MAX-PROBE_MIN));

    } else if (ll->state == IPV4LL_STATE_PROBING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration >= PROBE_NUM-2) {

        /* Send the last probe */
        arp_packet_probe(&out_packet, ll->address, &ll->mac_addr);
        out_packet_ready = 1;
        ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_ANNOUNCE, 1);

        ipv4ll_set_next_wakeup(ll, ANNOUNCE_WAIT, 0);

    } else if ((ll->state == IPV4LL_STATE_WAITING_ANNOUNCE && trigger == IPV4LL_TRIGGER_TIMEOUT) ||
               (ll->state == IPV4LL_STATE_ANNOUNCING && trigger == IPV4LL_TRIGGER_TIMEOUT && ll->iteration < ANNOUNCE_NUM-1)) {

        /* Send announcement packet */
        arp_packet_announcement(&out_packet, ll->address, &ll->mac_addr);
        out_packet_ready = 1;
        ipv4ll_set_state(ll, IPV4LL_STATE_ANNOUNCING, 0);

        ipv4ll_set_next_wakeup(ll, ANNOUNCE_INTERVAL, 0);

        if (ll->iteration == 0) {
            log_ipv4ll(ll, "ANNOUNCE");
            ll->claimed_address = ll->address;
            ll = ipv4ll_client_notify(ll, IPV4LL_EVENT_BIND);
            if (!ll || ll->state == IPV4LL_STATE_STOPPED)
                goto out;

            ll->conflict = 0;
        }

    } else if ((ll->state == IPV4LL_STATE_ANNOUNCING && trigger == IPV4LL_TRIGGER_TIMEOUT &&
                ll->iteration >= ANNOUNCE_NUM-1)) {

        ipv4ll_set_state(ll, IPV4LL_STATE_RUNNING, 0);
        ll->next_wakeup_valid = 0;

    } else if (trigger == IPV4LL_TRIGGER_PACKET) {

        int conflicted = 0;
        usec_t time_now;
        struct ether_arp* in_packet = (struct ether_arp*)trigger_data;

        assert(in_packet);

        if (IN_SET(ll->state, IPV4LL_STATE_ANNOUNCING, IPV4LL_STATE_RUNNING)) {

            if (ipv4ll_arp_conflict(ll, in_packet)) {

                r = sd_event_now(ll->event, clock_boottime_or_monotonic(), &time_now);
                if (r < 0)
                    goto out;

                /* Defend address */
                if (time_now > ll->defend_window) {
                    ll->defend_window = time_now + DEFEND_INTERVAL * USEC_PER_SEC;
                    arp_packet_announcement(&out_packet, ll->address, &ll->mac_addr);
                    out_packet_ready = 1;
                } else
                    conflicted = 1;
            }

        } else if (IN_SET(ll->state, IPV4LL_STATE_WAITING_PROBE,
                          IPV4LL_STATE_PROBING,
                          IPV4LL_STATE_WAITING_ANNOUNCE)) {

            conflicted = ipv4ll_arp_probe_conflict(ll, in_packet);
        }

        if (conflicted) {
            log_ipv4ll(ll, "CONFLICT");
            ll = ipv4ll_client_notify(ll, IPV4LL_EVENT_CONFLICT);
            if (!ll || ll->state == IPV4LL_STATE_STOPPED)
                goto out;

            ll->claimed_address = 0;

            /* Pick a new address */
            r = ipv4ll_pick_address(ll, &ll->address);
            if (r < 0)
                goto out;
            ll->conflict++;
            ll->defend_window = 0;
            ipv4ll_set_state(ll, IPV4LL_STATE_WAITING_PROBE, 1);

            if (ll->conflict >= MAX_CONFLICTS) {
                log_ipv4ll(ll, "MAX_CONFLICTS");
                ipv4ll_set_next_wakeup(ll, RATE_LIMIT_INTERVAL, PROBE_WAIT);
            } else
                ipv4ll_set_next_wakeup(ll, 0, PROBE_WAIT);

        }
    }

    if (out_packet_ready) {
        r = arp_network_send_raw_socket(ll->fd, &ll->link, &out_packet);
        if (r < 0) {
            log_ipv4ll(ll, "failed to send arp packet out");
            goto out;
        }
    }

    if (ll->next_wakeup_valid) {
        ll->timer = sd_event_source_unref(ll->timer);
        r = sd_event_add_time(ll->event, &ll->timer, clock_boottime_or_monotonic(),
                              ll->next_wakeup, 0, ipv4ll_timer, ll);
        if (r < 0)
            goto out;

        r = sd_event_source_set_priority(ll->timer, ll->event_priority);
        if (r < 0)
            goto out;

        r = sd_event_source_set_description(ll->timer, "ipv4ll-timer");
        if (r < 0)
            goto out;
    }

out:
    if (r < 0 && ll)
        ipv4ll_stop(ll, r);
}
Пример #23
0
static void automount_enter_waiting(Automount *a) {
        _cleanup_close_ int ioctl_fd = -1;
        int p[2] = { -1, -1 };
        char name[sizeof("systemd-")-1 + DECIMAL_STR_MAX(pid_t) + 1];
        char options[sizeof("fd=,pgrp=,minproto=5,maxproto=5,direct")-1
                     + DECIMAL_STR_MAX(int) + DECIMAL_STR_MAX(gid_t) + 1];
        bool mounted = false;
        int r, dev_autofs_fd;
        struct stat st;

        assert(a);
        assert(a->pipe_fd < 0);
        assert(a->where);

        set_clear(a->tokens);

        r = unit_fail_if_symlink(UNIT(a), a->where);
        if (r < 0)
                goto fail;

        (void) mkdir_p_label(a->where, 0555);

        unit_warn_if_dir_nonempty(UNIT(a), a->where);

        dev_autofs_fd = open_dev_autofs(UNIT(a)->manager);
        if (dev_autofs_fd < 0) {
                r = dev_autofs_fd;
                goto fail;
        }

        if (pipe2(p, O_NONBLOCK|O_CLOEXEC) < 0) {
                r = -errno;
                goto fail;
        }

        xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp());
        xsprintf(name, "systemd-"PID_FMT, getpid());
        if (mount(name, a->where, "autofs", 0, options) < 0) {
                r = -errno;
                goto fail;
        }

        mounted = true;

        p[1] = safe_close(p[1]);

        if (stat(a->where, &st) < 0) {
                r = -errno;
                goto fail;
        }

        ioctl_fd = open_ioctl_fd(dev_autofs_fd, a->where, st.st_dev);
        if (ioctl_fd < 0) {
                r = ioctl_fd;
                goto fail;
        }

        r = autofs_protocol(dev_autofs_fd, ioctl_fd);
        if (r < 0)
                goto fail;

        r = autofs_set_timeout(dev_autofs_fd, ioctl_fd, a->timeout_idle_usec);
        if (r < 0)
                goto fail;

        /* Autofs fun fact:
         *
         * Unless we close the ioctl fd here, for some weird reason
         * the direct mount will not receive events from the
         * kernel. */

        r = sd_event_add_io(UNIT(a)->manager->event, &a->pipe_event_source, p[0], EPOLLIN, automount_dispatch_io, a);
        if (r < 0)
                goto fail;

        (void) sd_event_source_set_description(a->pipe_event_source, "automount-io");

        a->pipe_fd = p[0];
        a->dev_id = st.st_dev;

        automount_set_state(a, AUTOMOUNT_WAITING);

        return;

fail:
        log_unit_error_errno(UNIT(a), r, "Failed to initialize automounter: %m");

        safe_close_pair(p);

        if (mounted) {
                r = repeat_unmount(a->where, MNT_DETACH);
                if (r < 0)
                        log_error_errno(r, "Failed to unmount, ignoring: %m");
        }

        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
}