/* * Receive events from netlink socket and generate events. */ static int __ni_rtevent_process_cb(struct nl_msg *msg, void *ptr) { const struct sockaddr_nl *sender = nlmsg_get_src(msg); struct nlmsghdr *nlh; ni_netconfig_t *nc; if ((nc = ni_global_state_handle(0)) == NULL) return NL_SKIP; if (sender->nl_pid != 0) { ni_error("ignoring rtnetlink event message from PID %u", sender->nl_pid); return NL_SKIP; } nlh = nlmsg_hdr(msg); if (__ni_rtevent_process(nc, sender, nlh) < 0) { ni_debug_events("ignoring %s rtnetlink event", ni_rtnl_msg_type_to_name(nlh->nlmsg_type, "unknown")); return NL_SKIP; } return NL_OK; }
static int nfc_netlink_event(struct nl_msg *n, void *arg) { struct sockaddr_nl *src = nlmsg_get_src(n); struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(n)); DBG("event 0x%x", gnlh->cmd); if (src->nl_pid) { near_error("WARNING: Wrong netlink message sender %d", src->nl_pid); return NL_SKIP; } switch (gnlh->cmd) { case NFC_EVENT_TARGETS_FOUND: DBG("Targets found"); nfc_netlink_event_targets_found(gnlh); break; case NFC_EVENT_TARGET_LOST: DBG("Target lost"); nfc_netlink_event_target_lost(gnlh); break; case NFC_EVENT_DEVICE_ADDED: DBG("Adapter added"); nfc_netlink_event_adapter(gnlh, true); break; case NFC_EVENT_DEVICE_REMOVED: DBG("Adapter removed"); nfc_netlink_event_adapter(gnlh, false); break; case NFC_CMD_DEP_LINK_UP: DBG("DEP link is up"); nfc_netlink_event_dep_up(gnlh); break; case NFC_CMD_DEP_LINK_DOWN: DBG("DEP link is down"); nfc_netlink_event_dep_down(gnlh); break; case NFC_EVENT_TM_ACTIVATED: DBG("Target mode activated"); nfc_netlink_event_tm_activated(gnlh); break; case NFC_EVENT_TM_DEACTIVATED: DBG("Target mode deactivated"); nfc_netlink_event_tm_deactivated(gnlh); break; } return NL_SKIP; }
/* Callback for sequence number check */ static int iz_cb_seq_check(struct nl_msg *msg, void *arg) { uint32_t seq; if(nlmsg_get_src(msg)->nl_groups) return NL_OK; seq = nlmsg_hdr(msg)->nlmsg_seq; if (seq == iz_seq) { if (!(nlmsg_hdr(msg)->nlmsg_flags & NLM_F_MULTI)) iz_seq ++; return NL_OK; } printf("Sequence number mismatch (%i, %i)!", seq, iz_seq); return NL_SKIP; }
static int event_msg_recv (struct nl_msg *msg, void *arg) { struct nl_sock *nlh = arg; struct nlmsghdr *hdr = nlmsg_hdr (msg); struct ucred *creds = nlmsg_get_creds (msg); const struct sockaddr_nl *snl; guint32 local_port; gboolean accept_msg = FALSE; /* Only messages sent from the kernel */ if (!creds || creds->uid != 0) { nm_log_dbg (LOGD_HW, "ignoring netlink message from UID %d", creds ? creds->uid : -1); return NL_SKIP; } snl = nlmsg_get_src (msg); g_assert (snl); /* Accept any messages from the kernel */ if (hdr->nlmsg_pid == 0 || snl->nl_pid == 0) accept_msg = TRUE; /* And any multicast message directed to our netlink PID, since multicast * currently requires CAP_ADMIN to use. */ local_port = nl_socket_get_local_port (nlh); if ((hdr->nlmsg_pid == local_port) && snl->nl_groups) accept_msg = TRUE; if (accept_msg == FALSE) { nm_log_dbg (LOGD_HW, "ignoring netlink message from PID %d (local PID %d, multicast %d)", hdr->nlmsg_pid, local_port, (hdr->nlmsg_flags & NLM_F_MULTI)); return NL_SKIP; } return NL_OK; }