int main(int argc, char* argv[]) { sock_fd = socket(PF_NETLINK, SOCK_RAW, 21); memset(&msg, 0, sizeof(msg)); memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); /* self pid */ src_addr.nl_groups = 0; /* not in mcast groups */ bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)); memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; /* For Linux Kernel */ dest_addr.nl_groups = 0; /* unicast */ nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD)); /* Fill the netlink message header */ nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); /* self pid */ nlh->nlmsg_flags = 0; /* Fill in the netlink message payload */ strcpy(NLMSG_DATA(nlh), "Hello you!"); iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_name = (void *)&dest_addr; msg.msg_namelen = sizeof(dest_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; printf(" Sending message. ...\n"); sendmsg(sock_fd, &msg, 0); /* Read message from kernel */ memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); printf(" Waiting message. ...\n"); recvmsg(sock_fd, &msg, 0); printf(" Received message payload: %s\n", NLMSG_DATA(nlh)); /* Close Netlink Socket */ close(sock_fd); }
void sample_input (struct sk_buff *__skb) { struct sk_buff *skb; struct nlmsghdr *nlh; unsigned int pid; int rc; int len = NLMSG_SPACE(1200); char data[100]; int dlen=0; skb = skb_get(__skb); if (skb->len >= NLMSG_SPACE(0)) { nlh = nlmsg_hdr(skb); dlen= nlh->nlmsg_len; pid = nlh->nlmsg_pid;/*发送进程ID */ if(dlen>100)dlen=100; memset(data,0,100); memcpy(data,NLMSG_DATA(nlh),dlen); printk("net_link: recv '%s' from process %d.\n",data,pid); kfree_skb(skb); skb = alloc_skb(len, GFP_ATOMIC); if (!skb) { printk("net_link: alloc_skb failed.\n"); return; } nlh = nlmsg_put(skb,0,0,0,1200,0); nlh ->nlmsg_len=dlen; NETLINK_CB(skb).pid = 0;/* 发自内核*/ memcpy(NLMSG_DATA(nlh), data, strlen(data)); rc = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT); if (rc < 0) { printk("net_link: unicast skb error\n"); } printk("net_link: send '%s' to process %d ok.\n",data,pid); } return; }
int netlink_test_compute(int fd, struct sockaddr_nl *daddr) { int res; char buf[40]; int *ptr; int addr_len = sizeof(struct sockaddr_nl); struct nlmsghdr *nlh; nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(12)); if (!nlh) { printf("malloc() error.\n"); return -1; } nlh->nlmsg_type = NLMSG_TEST_COMPUTE; nlh->nlmsg_flags = NLM_F_REQUEST; nlh->nlmsg_seq = 2; nlh->nlmsg_pid = getpid(); ptr = NLMSG_DATA(nlh); *ptr++ = NLMSG_TEST_COMPUTE_ADD; *ptr++ = 3; *ptr = 5; nlh->nlmsg_len = NLMSG_LENGTH(12); res = sendto(fd, nlh, NLMSG_SPACE(12), 0, (struct sockaddr *)daddr, addr_len); if (res == -1) { printf("sendto() error.\n"); goto error; } memset(buf, 0, 40); res = recvfrom(fd, buf, 40, 0, (struct sockaddr *)daddr, &addr_len); if (res == -1) { printf("recvfrom() error.\n"); goto error; } ptr = NLMSG_DATA((struct nlmsghdr *)buf); printf("3 + 5 = %d\n", *ptr); error: free(nlh); return res; }
static void nl_send_unicast_message(int dst_pid) { struct sk_buff *skb = NULL; struct nlmsghdr *nlh = NULL; int err; int bt_state; unsigned long flags; dev_info(shm_dev->dev, "Sending unicast message\n"); /* prepare the NL message for unicast */ skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD), GFP_KERNEL); if (!skb) { dev_err(shm_dev->dev, "%s:alloc_skb failed\n", __func__); return; } nlh = (struct nlmsghdr *)skb->data; nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); dev_dbg(shm_dev->dev, "nlh->nlmsg_len = %d\n", nlh->nlmsg_len); nlh->nlmsg_pid = 0; /* from kernel */ nlh->nlmsg_flags = 0; spin_lock_irqsave(&boot_lock, flags); bt_state = boot_state; spin_unlock_irqrestore(&boot_lock, flags); if (bt_state == BOOT_DONE) *(int *)NLMSG_DATA(nlh) = SHRM_NL_STATUS_MOD_ONLINE; else *(int *)NLMSG_DATA(nlh) = SHRM_NL_STATUS_MOD_OFFLINE; skb_put(skb, MAX_PAYLOAD); /* sender is in group 1<<0 */ NETLINK_CB(skb).pid = 0; /* from kernel */ NETLINK_CB(skb).dst_group = 0; /*unicast the message to the querying processes*/ err = netlink_unicast(shrm_nl_sk, skb, dst_pid, MSG_DONTWAIT); dev_dbg(shm_dev->dev, "ret val from nl-unicast = %d\n", err); }
static void print_ifinfomsg(const unsigned int msg_len) { printf("{len=%u, type=RTM_GETLINK, flags=NLM_F_DUMP" ", seq=0, pid=0}, {ifi_family=AF_UNIX" ", ifi_type=ARPHRD_LOOPBACK" ", ifi_index=" IFINDEX_LO_STR ", ifi_flags=IFF_UP, ifi_change=0}" ", {{nla_len=%u, nla_type=IFLA_PORT_SELF}", msg_len, msg_len - NLMSG_SPACE(hdrlen)); }
int main(int argc, char *argv[]) { struct sockaddr_nl saddr, daddr; struct nlmsghdr *nlhdr = NULL; struct msghdr msg; struct iovec iov; int sd; const char* text_line = "hello"; int ret = -1; printf("pid: %d\n", getpid()); sd = socket(AF_NETLINK, SOCK_RAW, NETLINK_USERSOCK); memset(&saddr, 0, sizeof(saddr)); memset(&daddr, 0, sizeof(daddr)); saddr.nl_family = AF_NETLINK; saddr.nl_pid = getpid(); saddr.nl_groups = 0; bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)); daddr.nl_family = AF_NETLINK; daddr.nl_pid = 0; daddr.nl_groups = 0; nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(1024)); memcpy(NLMSG_DATA(nlhdr), text_line, strlen(text_line)); memset(&msg, 0 ,sizeof(struct msghdr)); nlhdr->nlmsg_len = NLMSG_LENGTH(strlen(text_line)); nlhdr->nlmsg_pid = getpid(); /* self pid */ nlhdr->nlmsg_flags = 0; iov.iov_base = (void *)nlhdr; iov.iov_len = nlhdr->nlmsg_len; msg.msg_name = (void *)&daddr; msg.msg_namelen = sizeof(daddr); msg.msg_iov = &iov; msg.msg_iovlen = 1; ret = sendmsg(sd, &msg, 0); if (-1 == ret) { perror("sendmsg"); } // msg.msg_name = (void *)&saddr; // ret = recvmsg(sd, &msg, 0); // if (ret == -1) // { // perror("recvmsg"); // } close(sd); }
int nfnl_check_attributes(const struct nfnl_handle *h, const struct nlmsghdr *nlh, struct nfattr *nfa[]) { assert(h); assert(nlh); assert(nfa); int min_len; u_int8_t type = NFNL_MSG_TYPE(nlh->nlmsg_type); u_int8_t subsys_id = NFNL_SUBSYS_ID(nlh->nlmsg_type); const struct nfnl_subsys_handle *ssh; struct nfnl_callback *cb; if (subsys_id > NFNL_MAX_SUBSYS) return -EINVAL; ssh = &h->subsys[subsys_id]; cb = &ssh->cb[type]; #if 1 /* checks need to be enabled as soon as this is called from * somebody else than __nfnl_handle_msg */ if (type >= ssh->cb_count) return -EINVAL; min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); if (nlh->nlmsg_len < min_len) return -EINVAL; #endif memset(nfa, 0, sizeof(struct nfattr *) * cb->attr_count); if (nlh->nlmsg_len > min_len) { struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh)); int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); while (NFA_OK(attr, attrlen)) { unsigned int flavor = NFA_TYPE(attr); if (flavor) { if (flavor > cb->attr_count) { /* we have received an attribute from * the kernel which we don't understand * yet. We have to silently ignore this * for the sake of future compatibility */ continue; } nfa[flavor - 1] = attr; } attr = NFA_NEXT(attr, attrlen); } } return 0; }
void netlink_send(void) { struct sk_buff *skb; struct nlmsghdr *nlh; int a = strlen("Hi from the kernel"); int b = strlen("Test 2"); skb = alloc_skb(BUFFER, GFP_KERNEL); nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(0)); nlh->nlmsg_flags = 0; nlh->nlmsg_pid = 0; nlh->nlmsg_seq = 0; memcpy(skb_tail_pointer(skb), "Hi from the kernel", strlen("Hi from the kernel")+1); skb_put(skb, strlen("Hi from the kernel")); memcpy(skb_tail_pointer(skb), "Test 2", strlen("Test 2")+1); skb_put(skb, strlen("Test 2")); nlh->nlmsg_len = skb->len - NLMSG_SPACE(0); printk(KERN_ALERT "a: %d b: %d skb->len: %d\n", a, b, skb->len - NLMSG_SPACE(0)); netlink_unicast(nl_sk, skb, nlk_pid, 0); }
/* event_mutex supposed to be held */ static int __event_send(const void *buf, int buf_len) { int res = 0, len; struct sk_buff *skb; struct nlmsghdr *nlh; static u32 seq; /* protected by event_mutex */ TRACE_ENTRY(); if (ctr_open_state != ISCSI_CTR_OPEN_STATE_OPEN) goto out; len = NLMSG_SPACE(buf_len); skb = alloc_skb(NLMSG_SPACE(len), GFP_KERNEL); if (skb == NULL) { PRINT_ERROR("alloc_skb() failed (len %d)", len); res = -ENOMEM; goto out; } nlh = __nlmsg_put(skb, iscsid_pid, seq++, NLMSG_DONE, len - sizeof(*nlh), 0); memcpy(NLMSG_DATA(nlh), buf, buf_len); res = netlink_unicast(nl, skb, iscsid_pid, 0); if (res <= 0) { if (res != -ECONNREFUSED) PRINT_ERROR("netlink_unicast() failed: %d", res); else TRACE(TRACE_MINOR, "netlink_unicast() failed: %s. " "Not functioning user space?", "Connection refused"); goto out; } out: TRACE_EXIT_RES(res); return res; }
int main(){ sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_USER); if (sock_fd < 0){ return -1; } memset(&src_addr, 0, sizeof(src_addr)); src_addr.nl_family = AF_NETLINK; src_addr.nl_pid = getpid(); bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr)); memset(&dst_addr, 0, sizeof(dst_addr)); dst_addr.nl_family = AF_NETLINK; dst_addr.nl_pid = 0; dst_addr.nl_groups = 0; nlh = (struct nlmsghdr*)malloc(NLMSG_SPACE(MAX_PAYLOAD)); memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; strcpy(NLMSG_DATA(nlh), "Hello"); iov.iov_base = (void*)nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_name = (void*)&dst_addr; msg.msg_namelen = sizeof(dst_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; printf("Sending message to the kernel\n"); sendmsg(sock_fd, &msg, 0); printf("Received message payload: %s\n", NLMSG_DATA(nlh)); close(sock_fd); return 0; }
/* * Send Net Link interface ready indication to application daemon * Each netlink message will have a message of type tAniMsgHdr inside. */ void nl_srv_nl_ready_indication ( void ) { struct sk_buff *skb = NULL; struct nlmsghdr *nlh; int err; skb = alloc_skb(NLMSG_SPACE(sizeof(driverLoaded)), GFP_KERNEL); if (NULL == skb) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "NLINK: skb alloc fail %s", __func__); return; } nlh = (struct nlmsghdr *)skb->data; nlh->nlmsg_pid = 0; /* from kernel */ nlh->nlmsg_flags = 0; nlh->nlmsg_seq = 0; nlh->nlmsg_len = sizeof(driverLoaded); vos_mem_copy(((char *)nlh) + sizeof(struct nlmsghdr), driverLoaded, sizeof(driverLoaded)); skb_put(skb, NLMSG_SPACE(sizeof(driverLoaded))); /* sender is in group 1<<0 */ NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /*multicast the message to all listening processes*/ err = netlink_broadcast(nl_srv_sock, skb, 0, 1, GFP_KERNEL); if (err) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_LOW, "NLINK: Ready Indication Send Fail %s, err %d", __func__, err); } return; }
static int initialize(int32_t sock_fd) { char *mesg = "Hello"; memset(&dest_addr, 0, sizeof(dest_addr)); dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; /* For Linux Kernel */ dest_addr.nl_groups = 0; /* unicast */ if (nlh) { free(nlh); nlh = NULL; } nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_MSG_SIZE)); if (nlh == NULL) { fprintf(stderr, "Cannot allocate memory \n"); close(sock_fd); return -1; } memset(nlh, 0, NLMSG_SPACE(MAX_MSG_SIZE)); nlh->nlmsg_len = NLMSG_SPACE(MAX_MSG_SIZE); nlh->nlmsg_pid = getpid(); nlh->nlmsg_type = WLAN_NL_MSG_CNSS_DIAG; nlh->nlmsg_flags = NLM_F_REQUEST; memcpy(NLMSG_DATA(nlh), mesg, strlen(mesg)); iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_name = (void *)&dest_addr; msg.msg_namelen = sizeof(dest_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; if (sendmsg(sock_fd, &msg, 0) < 0) { android_printf("%s error ", __func__); return -1; } return 1; }
static int kget_host_stats(uint64_t transport_handle, uint32_t host_no, char *host_stats) { int rc = 0; int ev_size; struct iscsi_uevent ev; struct iovec iov[2]; char nlm_ev[NLMSG_SPACE(sizeof(struct iscsi_uevent))]; struct nlmsghdr *nlh; memset(&ev, 0, sizeof(struct iscsi_uevent)); ev.type = ISCSI_UEVENT_GET_HOST_STATS; ev.transport_handle = transport_handle; ev.u.get_host_stats.host_no = host_no; iov[1].iov_base = &ev; iov[1].iov_len = sizeof(ev); rc = __kipc_call(iov, 2); if (rc < 0) return rc; if ((rc = nl_read(ctrl_fd, nlm_ev, NLMSG_SPACE(sizeof(struct iscsi_uevent)), MSG_PEEK)) < 0) { log_error("can not read nlm_ev, error %d", rc); return rc; } nlh = (struct nlmsghdr *)nlm_ev; ev_size = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct nlmsghdr)); if ((rc = nlpayload_read(ctrl_fd, (void *)host_stats, ev_size, 0)) < 0) { log_error("can not read from NL socket, error %d", rc); return rc; } return rc; }
static void send_unicast(int dst_pid) { struct sk_buff *skb; struct nlmsghdr *nlh; if (netlink_sk == NULL) { pr_err("could not send unicast, no socket\n"); return; } /* prepare the message for unicast */ skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD), GFP_KERNEL); if (!skb) { pr_err("failed to allocate socket buffer\n"); return; } nlh = (struct nlmsghdr *)skb->data; nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = 0; /* from kernel */ nlh->nlmsg_flags = 0; if (modem_m6718_spi_is_boot_done()) { pr_debug("sending netlink unicast message %d\n", NETLINK_MODEM_STATUS_ONLINE); *(int *)NLMSG_DATA(nlh) = NETLINK_MODEM_STATUS_ONLINE; } else { pr_debug("sending netlink unicast message %d\n", NETLINK_MODEM_STATUS_OFFLINE); *(int *)NLMSG_DATA(nlh) = NETLINK_MODEM_STATUS_OFFLINE; } skb_put(skb, MAX_PAYLOAD); /* sender is in group 1<<0 */ NETLINK_CB(skb).pid = 0; /* from kernel */ NETLINK_CB(skb).dst_group = 0; /* unicast the message to the querying process */ netlink_unicast(netlink_sk, skb, dst_pid, MSG_DONTWAIT); }
static void quota2_log(unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const char *prefix) { ulog_packet_msg_t *pm; struct sk_buff *log_skb; size_t size; struct nlmsghdr *nlh; if (!qlog_nl_event) return; size = NLMSG_SPACE(sizeof(*pm)); size = max(size, (size_t)NLMSG_GOODSIZE); log_skb = alloc_skb(size, GFP_ATOMIC); if (!log_skb) { pr_err("xt_quota2: cannot alloc skb for logging\n"); return; } nlh = nlmsg_put(log_skb, /*pid*/0, /*seq*/0, qlog_nl_event, sizeof(*pm), 0); if (!nlh) { pr_err("xt_quota2: nlmsg_put failed\n"); kfree_skb(log_skb); return; } pm = nlmsg_data(nlh); if (skb->tstamp.tv64 == 0) __net_timestamp((struct sk_buff *)skb); pm->data_len = 0; pm->hook = hooknum; if (prefix != NULL) strlcpy(pm->prefix, prefix, sizeof(pm->prefix)); else *(pm->prefix) = '\0'; if (in) strlcpy(pm->indev_name, in->name, sizeof(pm->indev_name)); else pm->indev_name[0] = '\0'; if (out) strlcpy(pm->outdev_name, out->name, sizeof(pm->outdev_name)); else pm->outdev_name[0] = '\0'; NETLINK_CB(log_skb).dst_group = 1; pr_debug("throwing 1 packets to netlink group 1\n"); netlink_broadcast(nflognl, log_skb, 0, 1, GFP_ATOMIC); }
int _do_command(int type, struct user_stat_msg * request) { int sock; struct sockaddr_nl remote; struct sockaddr_nl local; struct nlmsghdr * nlhdr; struct iovec iov; struct msghdr msg; sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ACCOUNT); if(sock < 0){ return -1; } memset(&local, 0, sizeof(struct sockaddr_nl)); local.nl_family = AF_NETLINK; local.nl_pid = getpid(); local.nl_groups = 0; if(bind(sock, (struct sockaddr*)&local, sizeof(struct sockaddr_nl)) != 0){ close(sock); return -1; } memset(&remote, 0, sizeof(struct sockaddr_nl)); remote.nl_family = AF_NETLINK; remote.nl_pid = 0; remote.nl_groups = 0; memset(&msg, 0, sizeof(struct msghdr)); nlhdr = (struct nlmsghdr *)malloc(NLMSG_SPACE(sizeof(struct user_stat_entry) * 1024)); memcpy(NLMSG_DATA(nlhdr), (char *)request, sizeof(struct user_stat_msg)); nlhdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct user_stat_msg)); nlhdr->nlmsg_pid = getpid(); /* self pid */ nlhdr->nlmsg_flags = NLM_F_REQUEST; nlhdr->nlmsg_type = type; iov.iov_base = (void *)nlhdr; iov.iov_len = nlhdr->nlmsg_len; msg.msg_name = (void *)&remote; msg.msg_namelen = sizeof(remote); msg.msg_iov = &iov; msg.msg_iovlen = 1; int ret = sendmsg(sock, &msg, 0); if (ret == -1) { return -1; } free(nlhdr); return sock; }
/* * Broadcast Logging service ready indication to any Logging application * Each netlink message will have a message of type tAniMsgHdr inside. */ void wlan_logging_srv_nl_ready_indication(void) { struct sk_buff *skb = NULL; struct nlmsghdr *nlh; tAniNlHdr *wnl = NULL; int payload_len; int err; static int rate_limit; payload_len = sizeof(tAniHdr) + sizeof(wlan_logging_ready) + sizeof(wnl->radio); skb = dev_alloc_skb(NLMSG_SPACE(payload_len)); if (NULL == skb) { if (!rate_limit) { LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, "NLINK: skb alloc fail %s", __func__); } rate_limit = 1; return; } rate_limit = 0; nlh = nlmsg_put(skb, 0, 0, ANI_NL_MSG_LOG, payload_len, NLM_F_REQUEST); if (NULL == nlh) { LOGGING_TRACE(VOS_TRACE_LEVEL_ERROR, "%s: nlmsg_put() failed for msg size[%d]", __func__, payload_len); kfree_skb(skb); return; } wnl = (tAniNlHdr *) nlh; wnl->radio = 0; wnl->wmsg.type = ANI_NL_MSG_READY_IND_TYPE; wnl->wmsg.length = sizeof(wlan_logging_ready); memcpy((char*)&wnl->wmsg + sizeof(tAniHdr), wlan_logging_ready, sizeof(wlan_logging_ready)); /* sender is in group 1<<0 */ NETLINK_CB(skb).dst_group = WLAN_NLINK_MCAST_GRP_ID; /*multicast the message to all listening processes*/ err = nl_srv_bcast(skb); if (err) { LOGGING_TRACE(VOS_TRACE_LEVEL_INFO_LOW, "NLINK: Ready Indication Send Fail %s, err %d", __func__, err); } return; }
/* Process one complete nfnetlink message. */ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { const struct nfnl_callback *nc; const struct nfnetlink_subsystem *ss; int type, err; if (security_netlink_recv(skb, CAP_NET_ADMIN)) return -EPERM; if (provenance_netlink_recv(skb, CAP_NET_ADMIN)) return -EPERM; /* All the messages must at least contain nfgenmsg */ if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) return 0; type = nlh->nlmsg_type; replay: ss = nfnetlink_get_subsys(type); if (!ss) { #ifdef CONFIG_MODULES nfnl_unlock(); request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type)); nfnl_lock(); ss = nfnetlink_get_subsys(type); if (!ss) #endif return -EINVAL; } nc = nfnetlink_find_client(type, ss); if (!nc) return -EINVAL; { int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); struct nlattr *cda[ss->cb[cb_id].attr_count + 1]; struct nlattr *attr = (void *)nlh + min_len; int attrlen = nlh->nlmsg_len - min_len; err = nla_parse(cda, ss->cb[cb_id].attr_count, attr, attrlen, ss->cb[cb_id].policy); if (err < 0) return err; err = nc->call(nfnl, skb, nlh, (const struct nlattr **)cda); if (err == -EAGAIN) goto replay; return err; } }
int main(void) { skip_if_unavailable("/proc/self/fd/"); const int fd = create_nl_socket(NETLINK_ROUTE); const unsigned int hdrlen = sizeof(struct ndmsg); void *nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + sizeof(struct nda_cacheinfo)); static char pattern[4096]; fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); const unsigned int nla_type = 0xffff & NLA_TYPE_MASK; char nla_type_str[256]; sprintf(nla_type_str, "%#x /* NDA_??? */", nla_type); TEST_NLATTR_(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, nla_type, nla_type_str, 4, pattern, 4, print_quoted_hex(pattern, 4)); TEST_NLATTR(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, NDA_DST, 4, pattern, 4, print_quoted_hex(pattern, 4)); static const struct nda_cacheinfo ci = { .ndm_confirmed = 0xabcdedad, .ndm_used = 0xbcdaedad, .ndm_updated = 0xcdbadeda, .ndm_refcnt = 0xdeadbeda }; TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, NDA_CACHEINFO, pattern, ci, PRINT_FIELD_U("{", ci, ndm_confirmed); PRINT_FIELD_U(", ", ci, ndm_used); PRINT_FIELD_U(", ", ci, ndm_updated); PRINT_FIELD_U(", ", ci, ndm_refcnt); printf("}")); const uint16_t port = 0xabcd; TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, init_ndmsg, print_ndmsg, NDA_PORT, pattern, port, printf("htons(%u)", ntohs(port))); puts("+++ exited with 0 +++"); return 0; }
void send_event(int sock, char *buffer) { struct sockaddr_nl nladdr; struct msghdr msg; struct iovec iov; struct nlmsghdr *nlh = NULL; int buflen = NLMSG_SPACE(strlen(buffer) + 1); memset(&msg, 0, sizeof(msg)); memset(&nlh, 0, sizeof(nlh)); memset(&nladdr, 0, sizeof(nladdr)); memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = 0; /* 0 = send to Linux kernel */ nladdr.nl_groups = 0; /* 0 = unicast */ nlh = (struct nlmsghdr *)malloc(buflen); nlh->nlmsg_len = NLMSG_SPACE(buflen); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; strcpy(NLMSG_DATA(nlh), buffer); iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_name = (void *) &(nladdr); msg.msg_namelen = sizeof(nladdr); msg.msg_iov = &iov; msg.msg_iovlen = 1; if (DEBUG) printf("sending...\n"); sendmsg(sock, &msg, 0); return; }
void netsession_nl_rcv(struct sk_buff *skb) { u32 rlen; struct nlmsghdr *nlh; while(skb->len >= NLMSG_SPACE(0)) { nlh = nlmsg_hdr(skb); rlen = NLMSG_ALIGN(nlh->nlmsg_len); netsession_rcv_msg(skb, nlh); skb_pull(skb, rlen); } return; }
int netlink_sendto_kct(int fd, int type, const void *data, unsigned int size) { struct sockaddr_nl addr; static int sequence = 0; struct kct_packet req; int retval; if (NLMSG_SPACE(size) > CTM_MAX_NL_MSG) { errno = EMSGSIZE; return -1; } /* when about to overflow, start over */ if (++sequence < 0) sequence = 1; memset(&req, 0, sizeof(req)); req.nlh.nlmsg_len = NLMSG_SPACE(size); req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_REQUEST; req.nlh.nlmsg_seq = sequence; if (size && data) memcpy(NLMSG_DATA(&req.nlh), data, size); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; do { retval = sendto(fd, &req, req.nlh.nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr)); } while ((retval < 0) && (errno == EINTR)); if (retval < 0) return -1; return sequence; }
static int mnlk_send(char* info) { int size; struct sk_buff *skb; int old_tail; struct nlmsghdr *nlh; int retval; size = NLMSG_SPACE(strlen(info)); skb = alloc_skb(size, GFP_ATOMIC); nlh = nlmsg_put(skb, 0, 0, 0, NLMSG_SPACE(strlen(info))-sizeof(struct nlmsghdr), 0); old_tail = skb->tail; memcpy(NLMSG_DATA(nlh), info, strlen(info)); nlh->nlmsg_len = skb->tail - old_tail; NETLINK_CB(skb).dst_group = 0; spin_lock_bh(&http_netlink_lock); retval = netlink_unicast(nl_sk, skb, nl_pid, MSG_DONTWAIT); spin_unlock_bh(&http_netlink_lock); return 0; }
void rev_msg_fromkernel(int fd, struct msghdr *msgh, char *data) { struct iovec iov = {0}; struct nlmsghdr *nlh = NULL; int size = 0; nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(NETLINK_MSG_DATA_MAX)); if(!nlh) { printf("Malloc nlh fail\n"); return; } memset(NLMSG_DATA(nlh), 0, NETLINK_MSG_DATA_MAX); nlh->nlmsg_len = NLMSG_SPACE(NETLINK_MSG_DATA_MAX); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; msgh->msg_iov = &iov; msgh->msg_iovlen = 1; while(1) { size = recvmsg(fd, msgh, 0); if(size > 0) { memcpy(data, (char *) NLMSG_DATA(nlh), size); break; } } free(nlh); nlh = NULL; }
a_status_t acfg_net_indicate_event(struct net_device *dev, acfg_os_event_t *event, int send_iwevent) { struct sk_buff *skb; int err; __acfg_event_t fn; #if LINUX_VERSION_CODE >= KERNEL_VERSION (2,6,24) if (!net_eq(dev_net(dev), &init_net)) return A_STATUS_FAILED ; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION (2,6,24) skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); #else skb = nlmsg_new(NLMSG_SPACE(ACFG_MAX_PAYLOAD)); #endif if (!skb) return A_STATUS_ENOMEM ; err = ev_fill_info(skb, dev, RTM_NEWLINK, event); if (err < 0) { kfree_skb(skb); return A_STATUS_FAILED ; } NETLINK_CB(skb).dst_group = RTNLGRP_LINK; #if ATOPT_ORI_ATHEROS_BUG NETLINK_CB(skb).portid = 0; /* from kernel */ #else NETLINK_CB(skb).pid = 0; /* from kernel */ #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) NETLINK_CB(skb).dst_pid = 0; /* multicast */ #endif /* Send event to acfg */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) err = nlmsg_multicast(acfg_ev_sock, skb, 0, RTNLGRP_NOTIFY); #else rtnl_notify(skb, &init_net, 0, RTNLGRP_NOTIFY, NULL, GFP_ATOMIC); #endif if (send_iwevent) { /* Send iw event */ fn = iw_events[event->id]; if (fn != NULL) { fn(dev, &event->data); } } return A_STATUS_OK ; }
void nl_data_ready (struct sk_buff *__skb) { struct sk_buff *skb; struct nlmsghdr *nlh; u32 pid; int rc; int len = NLMSG_SPACE(1200); char str[100]; printk("net_link: data is ready to read.\n"); skb = skb_get(__skb); if (skb->len >= NLMSG_SPACE(0)) { nlh = nlmsg_hdr(skb); printk("net_link: recv %s.\n", (char *)NLMSG_DATA(nlh)); memcpy(str,NLMSG_DATA(nlh), sizeof(str)); pid = nlh->nlmsg_pid; /*pid of sending process */ printk("net_link: pid is %d\n", pid); kfree_skb(skb); skb = alloc_skb(len, GFP_ATOMIC); if (!skb){ printk(KERN_ERR "net_link: allocate failed.\n"); return; } nlh = nlmsg_put(skb,0,0,0,1200,0); NETLINK_CB(skb).pid = 0; /* from kernel */ memcpy(NLMSG_DATA(nlh), str, sizeof(str)); printk("net_link: going to send.\n"); rc = netlink_unicast(nl_sk, skb, pid, MSG_DONTWAIT); if (rc < 0) { printk(KERN_ERR "net_link: can not unicast skb (%d)\n", rc); } printk("net_link: send is ok.\n"); } return; }
static void nl_data_handler(struct sk_buff *__skb) { struct sk_buff *skb; struct nlmsghdr *nlh; int i; int len; char str[128]; MSG("we got netlink message\n"); len = NLMSG_SPACE(MAX_NL_MSG_LEN); skb = skb_get(__skb); if (skb == NULL) ERR("skb_get return NULL"); if (skb->len >= NLMSG_SPACE(0)) { /*presume there is 5byte payload at leaset */ MSG("length is enough\n"); nlh = nlmsg_hdr(skb); /* point to data which include in skb */ memcpy(str, NLMSG_DATA(nlh), sizeof(str)); for (i = 0; i < 3; i++) MSG("str[%d = %c]", i, str[i]); MSG("str[0] = %d, str[1] = %d, str[2] = %d\n", str[0], str[1], str[2]); if (str[0] == 'B' && str[1] == 'G' && str[2] == 'W') { MSG("got native daemon init command, record it's pid\n"); pid = nlh->nlmsg_pid; /*record the native process PID */ MSG("native daemon pid is %d\n", pid); } else { ERR("this is not BGW message, ignore it\n"); return; } } else { ERR("not engouth data length\n"); return; } kfree_skb(skb); send_command_to_daemon(ACK); return; }
/* Function to receive callback message from kernel */ void recvMsgFromKernel(void) { struct msg *ret; char *job_name[10] = {"", "ENCRYPT", "DECRYPT", "LIST", "REMOVE", "CHECKSUM", "COMPRESS", "DECOMPRESS", "CONCAT", "CHANGE_PRIORITY"}; nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD)); memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD)); nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD); nlh->nlmsg_pid = getpid(); nlh->nlmsg_flags = 0; iov.iov_base = (void *)nlh; iov.iov_len = nlh->nlmsg_len; msg.msg_iov = &iov; msg.msg_iovlen = 1; /* Read message from kernel */ recvmsg(netlinkSockFD, &msg, 0); ret = NLMSG_DATA(nlh); close(netlinkSockFD); if (ret->ret == 0) printf("Callback Status: Job with job id: %d and job_type: %s is Success\n", ret->job_id, job_name[ret->job_type]); else if (ret->ret == 1) printf("Callback Status: Job with job id: %d is Removed\n", ret->job_id); else { errno = -ret->ret; printf("Callback Status: Job with job id %d and "\ "job_type: %s is Failed with return value %d\n", ret->job_id, job_name[ret->job_type], ret->ret); perror(""); } }
/* Move data from tmp buffer into an skb. This is an extra copy, and * that is unfortunate. However, the copy will only occur when a record * is being written to user space, which is already a high-overhead * operation. (Elimination of the copy is possible, for example, by * writing directly into a pre-allocated skb, at the cost of wasting * memory. */ static void audit_log_move(struct audit_buffer *ab) { struct sk_buff *skb; char *start; int extra = ab->nlh ? 0 : NLMSG_SPACE(0); skb = skb_peek(&ab->sklist); if (!skb || skb_tailroom(skb) <= ab->len + extra) { skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC); if (!skb) { ab->len = 0; /* Lose information in ab->tmp */ audit_log_lost("out of memory in audit_log_move"); return; } __skb_queue_tail(&ab->sklist, skb); if (!ab->nlh) ab->nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(0)); } start = skb_put(skb, ab->len); memcpy(start, ab->tmp, ab->len); ab->len = 0; }
/* * Refill our pool of SKBs for use in emergencies (eg, when eating memory and * none can be allocated). */ static void toi_fill_skb_pool(struct user_helper_data *uhd) { while (uhd->pool_level < uhd->pool_limit) { struct sk_buff *new_skb = alloc_skb(NLMSG_SPACE(uhd->skb_size), TOI_ATOMIC_GFP); if (!new_skb) break; new_skb->next = uhd->emerg_skbs; uhd->emerg_skbs = new_skb; uhd->pool_level++; } }