예제 #1
0
/* Check if the netlink message fits into the remaining bytes */
int nlmsg_ok(const struct nlmsghdr *nlh, int rem)
{
	return rem >= (int)sizeof(struct nlmsghdr) &&
		rem >= nlmsg_len(nlh) &&
		nlmsg_len(nlh) >= (int) sizeof(struct nlmsghdr) &&
		nlmsg_len(nlh) <= (rem);
}
예제 #2
0
파일: nl.c 프로젝트: freeshare2011/ubridge
extern void *nlmsg_data(struct nlmsg *nlmsg)
{
	char *data = ((char *)nlmsg) + NLMSG_ALIGN(sizeof(struct nlmsghdr));
	if (!nlmsg_len(nlmsg))
		return NULL;
	return data;
}
예제 #3
0
static int
rtnetlink_rcv_msg(struct sk_buf *skb, struct nlmsghdr *nlh) {

//    struct net *net = sock_net(skb->sk);
    rtnl_doit_func doit;
    int sz_idx, kind;
    int family;
    int type;
    int err;

    type = nlh->nlmsg_type;
    if (type > RTM_MAX) {
        RTE_LOG(ERR, QoS, "Operation not supported!\n");
        return -EOPNOTSUPP;
    }

    type -= RTM_BASE;

    /* All the messages must have at least 1 byte length */
    if (nlmsg_len(nlh) < (int)sizeof(struct rtgenmsg)) {
        RTE_LOG(ERR, QoS, "Message is too short!\n");
        return 0;
    }

    family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
    sz_idx = type>>2;
    kind = type&3;

//    if (kind != 2 && !ns_capable(net->user_ns, CAP_NET_ADMIN))
//           return -EPERM;
//    if (kind != 2) {
//       RTE_LOG(ERR, QoS, "Operation is not permitted!\n");
//       return -EPERM;
//   }

    if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
//            struct sock *rtnl;
           rtnl_dumpit_func dumpit;
           rtnl_calcit_func calcit;
           u16 min_dump_alloc = 0;

           dumpit = rtnl_get_dumpit(family, type);
           if (dumpit == NULL)
                   return -EOPNOTSUPP;
           calcit = rtnl_get_calcit(family, type);
           if (calcit)
                   min_dump_alloc = calcit(skb, nlh);

//           __rtnl_unlock();
//           rtnl = net->rtnl;
           {
                   struct netlink_dump_control c = {
                           .dump           = dumpit,
                           .min_dump_alloc = min_dump_alloc,
                   };
                   err = netlink_dump_start(skb, nlh, &c);
           }
//            rtnl_lock();
           return err;
    }
예제 #4
0
/*通信示例函数*/
static void cloud_wlan_nl_get_test(struct nlmsghdr *nlh)
{
    void *payload;  
    struct sk_buff *out_skb;  
    void *out_payload;  
    struct nlmsghdr *out_nlh;  
    int payload_len; // with padding, but ok for echo   
    

	payload = nlmsg_data(nlh);	
	payload_len = nlmsg_len(nlh);  
	printk("payload_len = %d\n", payload_len);  
	printk("Recievid: %s, From: %d\n", (char *)payload, nlh->nlmsg_pid);	

	
	out_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); //分配足以存放默认大小的sk_buff  
	if (!out_skb)
		goto failure;  
	//skb, pid, seq, type, len
	out_nlh = nlmsg_put(out_skb, 0, 0, CW_NLMSG_RES_OK, MAX_DATA_PAYLOAD, 0); //填充协议头数据  
	if (!out_nlh)
		goto failure;  
	out_payload = nlmsg_data(out_nlh);	
	// 在响应中加入字符串,以示区别  
	snprintf(out_payload, MAX_DATA_PAYLOAD, "[kernel res info]: GETPID[%d] TYPE [%2X] OK\n", nlh->nlmsg_pid, nlh->nlmsg_type);
	nlmsg_unicast(sk, out_skb, nlh->nlmsg_pid); 
	return;
failure:  
	printk(" failed in fun dataready!\n");  
}
예제 #5
0
extern void *nlmsg_data(struct nlmsg *nlmsg)
{
	char *data = ((char *)nlmsg) + NLMSG_HDRLEN;
	if (!nlmsg_len(nlmsg))
		return NULL;
	return data;
}
예제 #6
0
파일: cba-ecc.c 프로젝트: winstard/GmSSL
void nl_recv_msg(struct sk_buff* skb){
	struct nlmsghdr *nlh;
	struct sk_buff* out;
	struct ec2m_request_st* req;
	struct ec2m_response_st resp;
	int pid;
	int size;
	char *buf;
	int r;
	
	nlh=(struct nlmsghdr*)skb->data;
	size = nlmsg_len(nlh);// - NLMSG_HDRLEN;

	pid = nlh->nlmsg_pid; /*pid of sending process */
	/* printk(KERN_INFO "Netlink received a new msg from %d, size: %d\n", pid, size); */
	buf = nlmsg_data(nlh);
	req = (struct ec2m_request_st*)buf;
	/* printk(KERN_INFO "got a request: %d, len: %d", req->func, req->len); */
	
	switch (req->func) {
	case REQ_IMPORT_KEY:
	{
		mm_256* key;
		key = (mm_256*) (buf + sizeof(struct ec2m_request_st));
		resp.result = k_ec2m_import_key(key);
		size = sizeof(struct ec2m_response_st);
		buf = kmalloc(size, GFP_KERNEL);
		memcpy(buf, &resp, sizeof(resp));
		break;
	}
	case REQ_PRIVATE_OP:
	{
		mm256_point_t* P;
		mm256_point_t Q;
		P = (mm256_point_t*) (buf + sizeof(struct ec2m_request_st));
		resp.result = k_ec2m_private_op(&Q, P);
		size = sizeof(struct ec2m_response_st) + sizeof(mm256_point_t);
		buf = kmalloc(size, GFP_KERNEL);
		memcpy(buf, &resp, sizeof(resp));
		memcpy(buf + sizeof(resp), &Q, sizeof(Q));
		break;
	}

	}

	out = nlmsg_new(size, 0);
	nlh = nlmsg_put(out, 0, 0, NLMSG_DONE, size, 0);
	NETLINK_CB(out).dst_group = 0; /* not in mcast group */
	memcpy(nlmsg_data(nlh), buf, size);
	r = nlmsg_unicast(sock_fd, out, pid);
	if (r < 0){
		printk(KERN_INFO "forward msg to %d failed, err code %d\n", pid, r);
	}
	kfree(buf);
}
예제 #7
0
/*
 * Change state of port (ie from forwarding to blocking etc)
 * Used by spanning tree in user space.
 */
static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
{
	struct net *net = sock_net(skb->sk);
	struct ifinfomsg *ifm;
	struct nlattr *protinfo;
	struct net_device *dev;
	struct net_bridge_port *p;
	u8 new_state;

	if (nlmsg_len(nlh) < sizeof(*ifm))
		return -EINVAL;

	ifm = nlmsg_data(nlh);
	if (ifm->ifi_family != AF_BRIDGE)
		return -EPFNOSUPPORT;

	protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
	if (!protinfo || nla_len(protinfo) < sizeof(u8))
		return -EINVAL;

	new_state = nla_get_u8(protinfo);
	if (new_state > BR_STATE_BLOCKING)
		return -EINVAL;

	dev = __dev_get_by_index(net, ifm->ifi_index);
	if (!dev)
		return -ENODEV;

	p = br_port_get_rtnl(dev);
	if (!p)
		return -EINVAL;

	/* if kernel STP is running, don't allow changes */
	if (p->br->stp_enabled == BR_KERNEL_STP)
		return -EBUSY;

	if (!netif_running(dev) ||
	    (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED))
		return -ENETDOWN;

	p->state = new_state;
	br_log_state(p);

	spin_lock_bh(&p->br->lock);
	br_port_state_selection(p->br);
	spin_unlock_bh(&p->br->lock);

	br_ifinfo_notify(RTM_NEWLINK, p);

	return 0;
}
예제 #8
0
/* Next netlink message in message stream */
struct nlmsghdr *nlmsg_next(struct nlmsghdr *nlh, int *remaining)
{
	struct nlmsghdr *next_nlh = NULL;
	int len = nlmsg_len(nlh);

	len = NLMSG_ALIGN(len);
	if (*remaining > 0 &&
	    len <= *remaining &&
	    len >= (int) sizeof(struct nlmsghdr)) {
		next_nlh = (struct nlmsghdr *)((char *)nlh + len);
		*remaining -= len;
	}

	return next_nlh;
}
예제 #9
0
/*
 * Change state of port (ie from forwarding to blocking etc)
 * Used by spanning tree in user space.
 */
static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
{
	struct ifinfomsg *ifm;
	struct nlattr *protinfo;
	struct net_device *dev;
	struct net_bridge_port *p;
	u8 new_state;

	if (nlmsg_len(nlh) < sizeof(*ifm))
		return -EINVAL;

	ifm = nlmsg_data(nlh);
	if (ifm->ifi_family != AF_BRIDGE)
		return -EPFNOSUPPORT;

	protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
	if (!protinfo || nla_len(protinfo) < sizeof(u8))
		return -EINVAL;

	new_state = nla_get_u8(protinfo);
	if (new_state > BR_STATE_BLOCKING)
		return -EINVAL;

	dev = __if_dev_get_by_index(ifm->ifi_index);
	if (!dev)
		return -ENODEV;

	p = dev->br_port;
	if (!p)
		return -EINVAL;

	/* if kernel STP is running, don't allow changes */
	if (p->br->stp_enabled)
		return -EBUSY;

	if (!if_dev_admin_up(dev) ||
	    (!if_dev_running(dev) && new_state != BR_STATE_DISABLED))
		return -ENETDOWN;

	p->state = new_state;
	br_log_state(p);
	return 0;
}
예제 #10
0
/* Receive messages from netlink socket. */
static void ath_netlink_receive(struct sk_buff *__skb)
{
	struct sk_buff *skb = NULL;
	struct nlmsghdr *nlh = NULL;
	u_int8_t *data = NULL;
	u_int32_t uid, pid, seq;

	skb = skb_get(__skb);
	if (skb) {
		/* process netlink message pointed by skb->data */
		nlh = (struct nlmsghdr *)skb->data;
		pid = NETLINK_CREDS(skb)->pid;
		pid = nlh->nlmsg_pid;
		uid = NETLINK_CREDS(skb)->uid;
		seq = nlh->nlmsg_seq;
		data = NLMSG_DATA(nlh);

		gpid = pid;
		ath_netlink_reply(pid, seq, data);
		rttm_issue_request(data, nlmsg_len(nlh));
		kfree_skb(skb);
	}
	return ;
}
예제 #11
0
파일: nfnetlink.c 프로젝트: Flipkart/linux
/* Process one complete nfnetlink message. */
static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	struct net *net = sock_net(skb->sk);
	const struct nfnl_callback *nc;
	const struct nfnetlink_subsystem *ss;
	int type, err;

	/* All the messages must at least contain nfgenmsg */
	if (nlmsg_len(nlh) < sizeof(struct nfgenmsg))
		return 0;

	type = nlh->nlmsg_type;
replay:
	rcu_read_lock();
	ss = nfnetlink_get_subsys(type);
	if (!ss) {
#ifdef CONFIG_MODULES
		rcu_read_unlock();
		request_module("nfnetlink-subsys-%d", NFNL_SUBSYS_ID(type));
		rcu_read_lock();
		ss = nfnetlink_get_subsys(type);
		if (!ss)
#endif
		{
			rcu_read_unlock();
			return -EINVAL;
		}
	}

	nc = nfnetlink_find_client(type, ss);
	if (!nc) {
		rcu_read_unlock();
		return -EINVAL;
	}

	{
		int min_len = nlmsg_total_size(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;
		__u8 subsys_id = NFNL_SUBSYS_ID(type);

		err = nla_parse(cda, ss->cb[cb_id].attr_count,
				attr, attrlen, ss->cb[cb_id].policy);
		if (err < 0) {
			rcu_read_unlock();
			return err;
		}

		if (nc->call_rcu) {
			err = nc->call_rcu(net->nfnl, skb, nlh,
					   (const struct nlattr **)cda);
			rcu_read_unlock();
		} else {
			rcu_read_unlock();
			nfnl_lock(subsys_id);
			if (rcu_dereference_protected(table[subsys_id].subsys,
				lockdep_is_held(&table[subsys_id].mutex)) != ss ||
			    nfnetlink_find_client(type, ss) != nc)
				err = -EAGAIN;
			else if (nc->call)
				err = nc->call(net->nfnl, skb, nlh,
						   (const struct nlattr **)cda);
			else
				err = -EINVAL;
			nfnl_unlock(subsys_id);
		}
		if (err == -EAGAIN)
			goto replay;
		return err;
	}
}
예제 #12
0
파일: module.c 프로젝트: jamorton/kerneldb
/**
 * Called by kernel for each new netlink socket message receieved
 */
static void kr_nl_recv(struct sk_buff *skb) {

    struct nlmsghdr * nlh = (struct nlmsghdr *)skb->data;
    kr_dataptr data = nlmsg_data(nlh);

    int size = nlmsg_len(nlh);
    int pid = nlh->nlmsg_pid;
    int seq = nlh->nlmsg_seq;

    KrDb* db = NULL; /* used differently by all switch cases */

    KrOutbuf outbuf = kr_outbuf(sizeof(u64));

    /* helper macros for reading message data */
#define NEXT_U8()  (*(u8* )((data += sizeof(u8))  - sizeof(u8)))
#define NEXT_U64() (*(u64*)((data += sizeof(u64)) - sizeof(u64)))
#define NEXT_PTR(len) ((data += len) - len)
#define GET_DB() do {                                       \
        db = kr_db_from_id(NEXT_U8());                      \
        if (!db) {                                          \
            printk(KERN_INFO "GET_DB WITH INVALID ID\n");   \
            return;                                         \
        }                                                   \
    } while (0)

    /* -------------- command type switch */

    switch (nlh->nlmsg_type) {

        //--------------------------------------------------
        // Command: OPEN
        //--------------------------------------------------
    case KR_COMMAND_OPEN: {
        const char * path = (const char *)data;
        printk(KERN_INFO "KR_COMMAND_OPEN - \"%s\"\n", path);
        kr_db_open(&db, path);
        kr_nl_send(pid, seq, KR_COMMAND_OPEN, &db->id, sizeof(db->id));
        break;
    }

        //--------------------------------------------------
        // Command: Close
        //--------------------------------------------------
    case KR_COMMAND_CLOSE: {
        GET_DB();
        //kr_db_close(db);
        break;
    }

        //--------------------------------------------------
        // Command: PUT
        //--------------------------------------------------
    case KR_COMMAND_PUT: {
        KrSlice key, val;

        GET_DB();
        key.size = NEXT_U64();
        key.data = NEXT_PTR(key.size);
        val.size = NEXT_U64();
        val.data = NEXT_PTR(val.size);
        kr_db_put(db, key, val);
        break;
    }

        //--------------------------------------------------
        // Command: GET
        //--------------------------------------------------
    case KR_COMMAND_GET: {
        u64 size;
        KrSlice key;
        GET_DB();
        key.size = NEXT_U64();
        key.data = NEXT_PTR(key.size);
        kr_db_get(db, key, &outbuf, &size);
        *(u64 *)outbuf.data = size;
        kr_nl_send(pid, seq, KR_COMMAND_GET, outbuf.data, sizeof(u64) + size);
        break;
    }

        //--------------------------------------------------
        // Command: BENCH
        //--------------------------------------------------
    case KR_COMMAND_BENCH: {
        GET_DB();
        printk(KERN_INFO "Running kr_bench(\"%s\")...\n", db->path);
        kr_bench(db);
        printk(KERN_INFO "...done.\n");
    }

    case KR_COMMAND_NOP:
    default:
        printk(KERN_INFO "Received unknown command\n");
        break;
    }
}
예제 #13
0
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
	u32			uid, pid, seq, sid;
	void			*data;
	struct audit_status	*status_get, status_set;
	int			err;
	struct audit_buffer	*ab;
	u16			msg_type = nlh->nlmsg_type;
	uid_t			loginuid; /* loginuid of sender */
	struct audit_sig_info   *sig_data;
	char			*ctx;
	u32			len;

	err = audit_netlink_ok(skb, msg_type);
	if (err)
		return err;

	/* As soon as there's any sign of userspace auditd,
	 * start kauditd to talk to it */
	if (!kauditd_task)
		kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
	if (IS_ERR(kauditd_task)) {
		err = PTR_ERR(kauditd_task);
		kauditd_task = NULL;
		return err;
	}

	pid  = NETLINK_CREDS(skb)->pid;
	uid  = NETLINK_CREDS(skb)->uid;
	loginuid = NETLINK_CB(skb).loginuid;
	sid  = NETLINK_CB(skb).sid;
	seq  = nlh->nlmsg_seq;
	data = NLMSG_DATA(nlh);

	switch (msg_type) {
	case AUDIT_GET:
		status_set.enabled	 = audit_enabled;
		status_set.failure	 = audit_failure;
		status_set.pid		 = audit_pid;
		status_set.rate_limit	 = audit_rate_limit;
		status_set.backlog_limit = audit_backlog_limit;
		status_set.lost		 = atomic_read(&audit_lost);
		status_set.backlog	 = skb_queue_len(&audit_skb_queue);
		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0,
				 &status_set, sizeof(status_set));
		break;
	case AUDIT_SET:
		if (nlh->nlmsg_len < sizeof(struct audit_status))
			return -EINVAL;
		status_get   = (struct audit_status *)data;
		if (status_get->mask & AUDIT_STATUS_ENABLED) {
			err = audit_set_enabled(status_get->enabled,
							loginuid, sid);
			if (err < 0) return err;
		}
		if (status_get->mask & AUDIT_STATUS_FAILURE) {
			err = audit_set_failure(status_get->failure,
							 loginuid, sid);
			if (err < 0) return err;
		}
		if (status_get->mask & AUDIT_STATUS_PID) {
			int old   = audit_pid;
			if (sid) {
				if ((err = selinux_sid_to_string(
						sid, &ctx, &len)))
					return err;
				else
					audit_log(NULL, GFP_KERNEL,
						AUDIT_CONFIG_CHANGE,
						"audit_pid=%d old=%d by auid=%u subj=%s",
						status_get->pid, old,
						loginuid, ctx);
				kfree(ctx);
			} else
				audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
					"audit_pid=%d old=%d by auid=%u",
					  status_get->pid, old, loginuid);
			audit_pid = status_get->pid;
		}
		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
			err = audit_set_rate_limit(status_get->rate_limit,
							 loginuid, sid);
		if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
			err = audit_set_backlog_limit(status_get->backlog_limit,
							loginuid, sid);
		break;
	case AUDIT_USER:
	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
	case AUDIT_FIRST_USER_MSG2...AUDIT_LAST_USER_MSG2:
		if (!audit_enabled && msg_type != AUDIT_USER_AVC)
			return 0;

		err = audit_filter_user(&NETLINK_CB(skb), msg_type);
		if (err == 1) {
			err = 0;
			ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
			if (ab) {
				audit_log_format(ab,
						 "user pid=%d uid=%u auid=%u",
						 pid, uid, loginuid);
				if (sid) {
					if (selinux_sid_to_string(
							sid, &ctx, &len)) {
						audit_log_format(ab, 
							" ssid=%u", sid);
						/* Maybe call audit_panic? */
					} else
						audit_log_format(ab, 
							" subj=%s", ctx);
					kfree(ctx);
				}
				audit_log_format(ab, " msg='%.1024s'",
					 (char *)data);
				audit_set_pid(ab, pid);
				audit_log_end(ab);
			}
		}
		break;
	case AUDIT_ADD:
	case AUDIT_DEL:
		if (nlmsg_len(nlh) < sizeof(struct audit_rule))
			return -EINVAL;
		if (audit_enabled == 2) {
			ab = audit_log_start(NULL, GFP_KERNEL,
					AUDIT_CONFIG_CHANGE);
			if (ab) {
				audit_log_format(ab,
						 "pid=%d uid=%u auid=%u",
						 pid, uid, loginuid);
				if (sid) {
					if (selinux_sid_to_string(
							sid, &ctx, &len)) {
						audit_log_format(ab,
							" ssid=%u", sid);
						/* Maybe call audit_panic? */
					} else
						audit_log_format(ab,
							" subj=%s", ctx);
					kfree(ctx);
				}
				audit_log_format(ab, " audit_enabled=%d res=0",
					audit_enabled);
				audit_log_end(ab);
			}
			return -EPERM;
		}
		/* fallthrough */
	case AUDIT_LIST:
		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
					   uid, seq, data, nlmsg_len(nlh),
					   loginuid, sid);
		break;
	case AUDIT_ADD_RULE:
	case AUDIT_DEL_RULE:
		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
			return -EINVAL;
		if (audit_enabled == 2) {
			ab = audit_log_start(NULL, GFP_KERNEL,
					AUDIT_CONFIG_CHANGE);
			if (ab) {
				audit_log_format(ab,
						 "pid=%d uid=%u auid=%u",
						 pid, uid, loginuid);
				if (sid) {
					if (selinux_sid_to_string(
							sid, &ctx, &len)) {
						audit_log_format(ab,
							" ssid=%u", sid);
						/* Maybe call audit_panic? */
					} else
						audit_log_format(ab,
							" subj=%s", ctx);
					kfree(ctx);
				}
				audit_log_format(ab, " audit_enabled=%d res=0",
					audit_enabled);
				audit_log_end(ab);
			}
			return -EPERM;
		}
		/* fallthrough */
	case AUDIT_LIST_RULES:
		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
					   uid, seq, data, nlmsg_len(nlh),
					   loginuid, sid);
		break;
	case AUDIT_SIGNAL_INFO:
		err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
		if (err)
			return err;
		sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
		if (!sig_data) {
			kfree(ctx);
			return -ENOMEM;
		}
		sig_data->uid = audit_sig_uid;
		sig_data->pid = audit_sig_pid;
		memcpy(sig_data->ctx, ctx, len);
		kfree(ctx);
		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 
				0, 0, sig_data, sizeof(*sig_data) + len);
		kfree(sig_data);
		break;
	default:
		err = -EINVAL;
		break;
	}

	return err < 0 ? err : 0;
}