static void ntl_receive(struct sock *sk, int len)
{
    int err;
    struct sk_buff *skb;
    pid_t pid;
    struct nlmsghdr *nl_header;
    __u32 seq;
    struct pimfor_hdr *header;
    char *data;
    int version;
    int operation;
    unsigned long oid;
    int dev_id;
    int flags;
    unsigned long length;
  	struct net_device *dev;

#ifdef DRIVER_DEBUG
    printk(KERN_INFO "ntl_receive: sock %p, len %d \n", sk, len);
#endif

    do
    {
        if (rtnl_shlock_nowait())
                return;

        while ( (skb = skb_dequeue(&sk->receive_queue)) != NULL )
        {
            pid = NETLINK_CB(skb).pid;
            nl_header = (struct nlmsghdr*) skb->data;
            seq = nl_header->nlmsg_seq;
            header = (struct pimfor_hdr*)(skb->data+(sizeof(struct nlmsghdr)));
            data = PIMFOR_DATA(header);

            if ( nl_header->nlmsg_type == NETLINK_TYPE_PIMFOR )
            {
                pimfor_decode_header(header, &version, &operation, &oid, &dev_id, &flags, &length);

                if (version == PIMFOR_VERSION_1) {

                    err = mgt_request( DEV_NETWORK, dev_id, pid, seq, operation, oid, data, length );

                    if ( err < 0 ) {
                        printk(KERN_INFO "ntl_receive: mgt_request(%d, %d, %d, %x, %d, %x, %d) returned %d\n",
                               DEV_NETWORK, dev_id, pid, seq, operation, oid, length, err );
                        netlink_ack(skb, nl_header, -EOPNOTSUPP );
                    }

                } else {
                    printk(KERN_ERR "ntl_receive: version (%d) != PIMFOR_VERSION_1\n", version );
                    netlink_ack(skb, nl_header, -EOPNOTSUPP );
                }
            } else {
                printk(KERN_ERR "nl_header->nlmsg_type (%d) != NETLINK_TYPE_PIMFOR\n", nl_header->nlmsg_type );
                netlink_ack(skb, nl_header, -EOPNOTSUPP );
            }

            kfree_skb(skb);
        }
        up(&rtnl_sem);

    } while (nl_sock && nl_sock->receive_queue.qlen);
}
示例#2
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_ctxid_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_ctxid_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;
    /* 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;
    /* 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_ctxid_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;
}
static int ntl_transmit(pid_t pid, int seq, int operation, int oid, long *data, unsigned long data_len,
                        int dev_type, int dev_id )
{
    unsigned char *old_tail;
    struct sk_buff *skb;
    struct nlmsghdr *nlh;
    struct pimfor_hdr *pimfor_hdr;
    size_t size;

    int err = 0;
    /* Trap group is mapped to dev_type. */
    unsigned int trapgrp = dev_type;

#ifdef DRIVER_DEBUG
    printk(KERN_INFO "ntl_transmit: pid %d, seq %d, oper %d, oid %d, data ptr %p, data_len %lu, dev_id %d \n",
                       pid, seq, operation, oid, data, data_len, dev_id);
#endif

    if ( nl_sock == NULL ) {
        printk(KERN_ERR "ntl_transmit: no nl_sock\n");
        return -EPFNOSUPPORT;
    }

    size = NLMSG_LENGTH(data_len + sizeof(struct pimfor_hdr));
    skb = alloc_skb(size, GFP_ATOMIC);

    if ( skb ) {

        old_tail = skb->tail;
        nlh = NLMSG_PUT(skb, pid, seq, NETLINK_TYPE_PIMFOR, size - NLMSG_ALIGN(sizeof(struct nlmsghdr)));
        pimfor_hdr = (struct pimfor_hdr *)NLMSG_DATA(nlh);

        pimfor_encode_header(operation, oid, dev_id, 0 /*flags*/, data_len, pimfor_hdr);
        /* Add data after the PIMFOR header */
        memcpy(PIMFOR_DATA(pimfor_hdr), data, data_len);

        nlh->nlmsg_len = skb->tail - old_tail;
        NETLINK_CB(skb).dst_groups = 0;
    } else {

        printk(KERN_ERR "ntl_transmit: alloc_skb failed\n");
        return -EPFNOSUPPORT;
    }

    if (pid != 0 ) {
        err = netlink_unicast(nl_sock, skb, pid, MSG_DONTWAIT);
    } else {
        if (trapgrp) {
            netlink_broadcast(nl_sock, skb, pid, trapgrp ,GFP_ATOMIC );
        }
        else {
            printk(KERN_WARNING "No trap group defined, drop packet.\n");
            kfree_skb(skb);
        }
    }

    return err;

nlmsg_failure:
    if ( skb )
            kfree_skb(skb);
    printk(KERN_ERR "ntl_transmit: NLMSG_PUT failed\n");
    return -EPFNOSUPPORT;
}
static char* process_crypto_request(u8 opcode, char* send_msg, int send_msg_size, int* result_len, int* ret) {
	struct sk_buff *skb_in = NULL;
    struct sk_buff *skb_out = NULL;
    struct nlmsghdr *nlh = NULL;
	//char* rev_msg = NULL;
	char* result  = NULL;
	int rc = 0;
	int ready = 0;
	
	
	skb_in = nlmsg_new(send_msg_size, 0);
	if (!skb_in) {
		printk("%s %s Failed to allocate new skb: \n", PUB_CRYPTO_DEBUG, __FUNCTION__);
    	return NULL;
	}
	
	nlh = nlmsg_put(skb_in, 0, 0, NLMSG_DONE, send_msg_size, 0);
	NETLINK_CB(skb_in).dst_group = 0;
	memcpy(nlmsg_data(nlh), send_msg, send_msg_size);
	
	mutex_lock(&crypto_send_mutex);
	rc = nlmsg_unicast(crypto_sock, skb_in, user_fipscryptod_pid);
	mutex_unlock(&crypto_send_mutex);
	
    
	if (rc < 0) {
		printk(KERN_INFO "Error while sending bak to user, err id: %d\n", rc);
		return NULL;
	}
	
    //*******Reset the memory to hide plaintext!!!!!!
    memset(send_msg, 0, send_msg_size);
    
	{
		DECLARE_WAITQUEUE(wait, current);
		set_current_state(TASK_INTERRUPTIBLE);
		add_wait_queue(&event_wait_crypto_results, &wait);
	
	    while (!ready) {
			schedule_timeout_interruptible(CRYPTO_MAX_TIMEOUT);
			mutex_lock(&crypto_data_ready_mutex);
		    ready = g_data_ready;
		    g_data_ready = 0;
		    mutex_unlock(&crypto_data_ready_mutex);
		}
	
		set_current_state(TASK_RUNNING);
		remove_wait_queue(&event_wait_crypto_results, &wait);
   		
   		skb_out = skb_dequeue(&crypto_sock->sk_receive_queue);
   		
   		if(g_result_status == PUB_CRYPTO_ERROR) {
   			printk("%s %s FIPS_CRYPTO_ERROR!!!\n", PUB_CRYPTO_DEBUG, __FUNCTION__);
   			if(skb_out) {
	   			kfree_skb(skb_out);
   			}
   			result = NULL; goto out;
   		}
		
   		if(g_result.ret == -1) {
   			printk("%s %s failed to opcode(%d)!!!\n", PUB_CRYPTO_DEBUG, __FUNCTION__, opcode);
   			result = NULL; goto out;
   		}

   		if(opcode == OP_RSA_ENC || opcode == OP_RSA_DEC ||
   				opcode == OP_DH_DEC || opcode == OP_DH_ENC) {
   			*result_len = sizeof(dek_t);
   			result = kmalloc(*result_len, GFP_KERNEL);
   			memcpy(result, &(g_result.dek), *result_len);
   		}
   		*ret = (int)g_result.ret;
	}

out:
	mutex_unlock(&crypto_receive_mutex);
	return result;
}
INT MV_CC_ICCNetWrite(pMV_CC_ICCNet_t pHandle, UCHAR *pDatagramBuf)
{
	int res;
	MV_OSAL_CPUID_U8_t DstCpu;
	unsigned long flags;
	
	/* Parameter Check */
	if (//(pHandle == NULL) ||
		//(pDatagramBuf ==  NULL) ||
		((DstCpu = ICCP_DstCPU(pDatagramBuf)) >= MV_OSAL_CPU_NUM))
		MV_OSAL_ErrorHandle("MV_CC_ICCNetWrite", E_INVALIDARG);

	if (DstCpu != MV_OSAL_CPU_LOCAL)
	{
		res = MV_CC_StartStatus_Check();
		if (res == MV_CC_STATUS_OK)
		{
			PVOID pPtr;
			pPtr = MV_CC_HAL_GetFIFOArrayAddr(&(pHandle->m_pHW));
			if (pPtr == NULL)
				MV_OSAL_ErrorHandle("MV_CC_ICCNetWrite MV_CC_HAL_GetFIFOArrayAddr pPtr", E_POINTER);		
			
			/* ICC FIFO Array Initialize */
			res = MV_CC_ICCFIFOArrayInit(&(pHandle->m_FIFOArray), pPtr, MV_OSAL_CPU_LOCAL);
			if (res < 0)
				MV_OSAL_ErrorHandle("MV_CC_ICCNetWrite MV_CC_ICCFIFOArrayInit", res);	
				
			printk(KERN_ALERT "CPU-%d Check CC StartStatus = INITED\n", MV_OSAL_CPU_LOCAL);
		}
		else
		if (res != S_OK)
			return E_NOTREADY;
		
	  	// Close interrupt
	  	local_irq_save(flags);
	  	
		res = MV_CC_ICCFIFOArrayWrite(&(pHandle->m_FIFOArray),
									  DstCpu, 
									  pDatagramBuf);
										  
		switch (res) 
		{	
			case S_OK:
					
				pHandle->m_WrCount++;
				
				/* interrupt to Dst CPU */
				res = MV_CC_HAL_SemPost(&(pHandle->m_pHW), DstCpu);
				if (res != S_OK)
				{
					pHandle->m_WrSemErrCount++;
				}
				break;
					
			case E_FULL:
				pHandle->m_WrFullCount++;
				break;
			
			default:
				break;
		}
		
		// Restore interrupt
		local_irq_restore(flags);
	}
	else
	{
  		struct sk_buff * skb = NULL;
  		struct nlmsghdr * nlhdr = NULL;
  		int len = MV_CC_ICCFIFO_FRAME_SIZE;
  		unsigned int dst_pid;
  				
		skb = nlmsg_new(len, GFP_KERNEL);		//Linux Kernel 2.6.20
		if (skb == NULL)
	    {
			LOGPRINTF((KERN_ALERT "[MV_ICCNet] Can't create a netlink message.\n"));
			return E_OUTOFMEMORY;
	    }
    
	    nlhdr = nlmsg_put(skb, 0, 0, 0, len, 0);
		memcpy(NLMSG_DATA(nlhdr), pDatagramBuf, len);
	    NETLINK_CB(skb).pid = 0;
	    NETLINK_CB(skb).dst_group = NETLINK_GALOIS_CC_GROUP;
	
	    dst_pid = uiPidTable_GetLinuxPID(ICCP_DstProcess(pDatagramBuf));
	    if (dst_pid == 0)
	    {
		    // set MSG_DONTWAIT for a Nonblocking io, avoid sleep in netlink_broadcast
		    // set GFP_ATOMIC for a Nonblocking io, avoid sleep in netlink_broadcast	
	        res = netlink_broadcast(pMV_ICCNet_netlink_sock, skb, 0, NETLINK_GALOIS_CC_GROUP, GFP_KERNEL);
    
		}
	    else
	    {
	    	res = netlink_unicast(pMV_ICCNet_netlink_sock, skb, dst_pid, MSG_DONTWAIT);
	    	
	    }
  		
	    res = S_OK;
	}
	
	return res;
}
示例#6
0
static int do_getlink(struct sk_buff *in_skb, struct nlmsghdr* in_nlh, void *arg)
{
	struct ifinfomsg  *ifm = NLMSG_DATA(in_nlh);
	struct rtattr    **ida = arg;
	struct net_device *dev;
	struct ifinfomsg *r;
	struct nlmsghdr  *nlh;
	int err = -ENOBUFS;
	struct sk_buff *skb;
	unsigned char	 *b;
	char *iw_buf = NULL;
	int iw_buf_len = 0;

	if (ifm->ifi_index >= 0)
		dev = dev_get_by_index(ifm->ifi_index);
	else
		return -EINVAL;
	if (!dev)
		return -ENODEV;

#ifdef CONFIG_NET_WIRELESS_RTNETLINK
	if (ida[IFLA_WIRELESS - 1]) {

		/* Call Wireless Extensions. We need to know the size before
		 * we can alloc. Various stuff checked in there... */
		err = wireless_rtnetlink_get(dev, RTA_DATA(ida[IFLA_WIRELESS - 1]), ida[IFLA_WIRELESS - 1]->rta_len, &iw_buf, &iw_buf_len);
		if (err)
			goto out;
	}
#endif	/* CONFIG_NET_WIRELESS_RTNETLINK */

	/* Create a skb big enough to include all the data.
	 * Some requests are way bigger than 4k... Jean II */
	skb = alloc_skb((NLMSG_LENGTH(sizeof(*r))) + (RTA_SPACE(iw_buf_len)),
			GFP_KERNEL);
	if (!skb)
		goto out;
	b = skb->tail;

	/* Put in the message the usual good stuff */
	nlh = NLMSG_PUT(skb, NETLINK_CB(in_skb).pid, in_nlh->nlmsg_seq,
			RTM_NEWLINK, sizeof(*r));
	r = NLMSG_DATA(nlh);
	r->ifi_family = AF_UNSPEC;
	r->__ifi_pad = 0;
	r->ifi_type = dev->type;
	r->ifi_index = dev->ifindex;
	r->ifi_flags = dev->flags;
	r->ifi_change = 0;

	/* Put the wireless payload if it exist */
	if(iw_buf != NULL)
		RTA_PUT(skb, IFLA_WIRELESS, iw_buf_len,
			iw_buf + IW_EV_POINT_OFF);

	nlh->nlmsg_len = skb->tail - b;

	/* Needed ? */
	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;

	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
	if (err > 0)
		err = 0;
out:
	if(iw_buf != NULL)
		kfree(iw_buf);
	dev_put(dev);
	return err;

rtattr_failure:
nlmsg_failure:
	kfree_skb(skb);
	goto out;
}
示例#7
0
/**
 * kobject_uevent_env - send an uevent with environmental data
 *
 * @action: action that is happening (usually KOBJ_MOVE)
 * @kobj: struct kobject that the action is happening to
 * @envp_ext: pointer to environmental data
 *
 * Returns 0 if kobject_uevent() is completed with success or the
 * corresponding error when it fails.
 */
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
			char *envp_ext[])
{
	char **envp;
	char *buffer;
	char *scratch;
	const char *action_string;
	const char *devpath = NULL;
	const char *subsystem;
	struct kobject *top_kobj;
	struct kset *kset;
	struct kset_uevent_ops *uevent_ops;
	u64 seq;
	char *seq_buff;
	int i = 0;
	int retval = 0;
	int j;

	pr_debug("%s\n", __FUNCTION__);

	action_string = action_to_string(action);
	if (!action_string) {
		pr_debug("kobject attempted to send uevent without action_string!\n");
		return -EINVAL;
	}

	/* search the kset we belong to */
	top_kobj = kobj;
	if (!top_kobj->kset && top_kobj->parent) {
		do {
			top_kobj = top_kobj->parent;
		} while (!top_kobj->kset && top_kobj->parent);
	}
	if (!top_kobj->kset) {
		pr_debug("kobject attempted to send uevent without kset!\n");
		return -EINVAL;
	}

	kset = top_kobj->kset;
	uevent_ops = kset->uevent_ops;

	/*  skip the event, if the filter returns zero. */
	if (uevent_ops && uevent_ops->filter)
		if (!uevent_ops->filter(kset, kobj)) {
			pr_debug("kobject filter function caused the event to drop!\n");
			return 0;
		}

	/* environment index */
	envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL);
	if (!envp)
		return -ENOMEM;

	/* environment values */
	buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
	if (!buffer) {
		retval = -ENOMEM;
		goto exit;
	}

	/* complete object path */
	devpath = kobject_get_path(kobj, GFP_KERNEL);
	if (!devpath) {
		retval = -ENOENT;
		goto exit;
	}

	/* originating subsystem */
	if (uevent_ops && uevent_ops->name)
		subsystem = uevent_ops->name(kset, kobj);
	else
		subsystem = kobject_name(&kset->kobj);

	/* event environemnt for helper process only */
	envp[i++] = "HOME=/";
	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";

	/* default keys */
	scratch = buffer;
	envp [i++] = scratch;
	scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
	envp [i++] = scratch;
	scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
	envp [i++] = scratch;
	scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
	for (j = 0; envp_ext && envp_ext[j]; j++)
		envp[i++] = envp_ext[j];
	/* just reserve the space, overwrite it after kset call has returned */
	envp[i++] = seq_buff = scratch;
	scratch += strlen("SEQNUM=18446744073709551616") + 1;

	/* let the kset specific function add its stuff */
	if (uevent_ops && uevent_ops->uevent) {
		retval = uevent_ops->uevent(kset, kobj,
				  &envp[i], NUM_ENVP - i, scratch,
				  BUFFER_SIZE - (scratch - buffer));
		if (retval) {
			pr_debug ("%s - uevent() returned %d\n",
				  __FUNCTION__, retval);
			goto exit;
		}
	}

	/* we will send an event, request a new sequence number */
	spin_lock(&sequence_lock);
	seq = ++uevent_seqnum;
	spin_unlock(&sequence_lock);
	sprintf(seq_buff, "SEQNUM=%llu", (unsigned long long)seq);

#if defined(CONFIG_NET)
	/* send netlink message */
	if (uevent_sock) {
		struct sk_buff *skb;
		size_t len;

		/* allocate message with the maximum possible size */
		len = strlen(action_string) + strlen(devpath) + 2;
		skb = alloc_skb(len + BUFFER_SIZE, GFP_KERNEL);
		if (skb) {
			/* add header */
			scratch = skb_put(skb, len);
			sprintf(scratch, "%s@%s", action_string, devpath);

			/* copy keys to our continuous event payload buffer */
			for (i = 2; envp[i]; i++) {
				len = strlen(envp[i]) + 1;
				scratch = skb_put(skb, len);
				strcpy(scratch, envp[i]);
			}

			NETLINK_CB(skb).dst_group = 1;
			netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
		}
	}
#endif

	/* call uevent_helper, usually only enabled during early boot */
	if (uevent_helper[0]) {
		char *argv [3];

		argv [0] = uevent_helper;
		argv [1] = (char *)subsystem;
		argv [2] = NULL;
		call_usermodehelper (argv[0], argv, envp, 0);
	}

exit:
	kfree(devpath);
	kfree(buffer);
	kfree(envp);
	return retval;
}
示例#8
0
/* HSR_C_GET_NODE_STATUS lets userspace query the internal HSR node table
 * about the status of a specific node in the network, defined by its MAC
 * address.
 *
 * Input: hsr ifindex, node mac address
 * Output: hsr ifindex, node mac address (copied from request),
 *	   age of latest frame from node over slave 1, slave 2 [ms]
 */
static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info)
{
    /* For receiving */
    struct nlattr *na;
    struct net_device *hsr_dev;

    /* For sending */
    struct sk_buff *skb_out;
    void *msg_head;
    struct hsr_priv *hsr;
    struct hsr_port *port;
    unsigned char hsr_node_addr_b[ETH_ALEN];
    int hsr_node_if1_age;
    u16 hsr_node_if1_seq;
    int hsr_node_if2_age;
    u16 hsr_node_if2_seq;
    int addr_b_ifindex;
    int res;

    if (!info)
        goto invalid;

    na = info->attrs[HSR_A_IFINDEX];
    if (!na)
        goto invalid;
    na = info->attrs[HSR_A_NODE_ADDR];
    if (!na)
        goto invalid;

    hsr_dev = __dev_get_by_index(genl_info_net(info),
                                 nla_get_u32(info->attrs[HSR_A_IFINDEX]));
    if (!hsr_dev)
        goto invalid;
    if (!is_hsr_master(hsr_dev))
        goto invalid;


    /* Send reply */

    skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
    if (!skb_out) {
        res = -ENOMEM;
        goto fail;
    }

    msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
                           info->snd_seq, &hsr_genl_family, 0,
                           HSR_C_SET_NODE_STATUS);
    if (!msg_head) {
        res = -ENOMEM;
        goto nla_put_failure;
    }

    res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
    if (res < 0)
        goto nla_put_failure;

    hsr = netdev_priv(hsr_dev);
    res = hsr_get_node_data(hsr,
                            (unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]),
                            hsr_node_addr_b,
                            &addr_b_ifindex,
                            &hsr_node_if1_age,
                            &hsr_node_if1_seq,
                            &hsr_node_if2_age,
                            &hsr_node_if2_seq);
    if (res < 0)
        goto nla_put_failure;

    res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN,
                  nla_data(info->attrs[HSR_A_NODE_ADDR]));
    if (res < 0)
        goto nla_put_failure;

    if (addr_b_ifindex > -1) {
        res = nla_put(skb_out, HSR_A_NODE_ADDR_B, ETH_ALEN,
                      hsr_node_addr_b);
        if (res < 0)
            goto nla_put_failure;

        res = nla_put_u32(skb_out, HSR_A_ADDR_B_IFINDEX, addr_b_ifindex);
        if (res < 0)
            goto nla_put_failure;
    }

    res = nla_put_u32(skb_out, HSR_A_IF1_AGE, hsr_node_if1_age);
    if (res < 0)
        goto nla_put_failure;
    res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq);
    if (res < 0)
        goto nla_put_failure;
    rcu_read_lock();
    port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A);
    if (port)
        res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX,
                          port->dev->ifindex);
    rcu_read_unlock();
    if (res < 0)
        goto nla_put_failure;

    res = nla_put_u32(skb_out, HSR_A_IF2_AGE, hsr_node_if2_age);
    if (res < 0)
        goto nla_put_failure;
    res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq);
    if (res < 0)
        goto nla_put_failure;
    rcu_read_lock();
    port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
    if (port)
        res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX,
                          port->dev->ifindex);
    rcu_read_unlock();
    if (res < 0)
        goto nla_put_failure;

    genlmsg_end(skb_out, msg_head);
    genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid);

    return 0;

invalid:
    netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL);
    return 0;

nla_put_failure:
    kfree_skb(skb_out);
    /* Fall through */

fail:
    return res;
}
示例#9
0
/* Get a list of MacAddressA of all nodes known to this node (including self).
 */
static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info)
{
    /* For receiving */
    struct nlattr *na;
    struct net_device *hsr_dev;

    /* For sending */
    struct sk_buff *skb_out;
    void *msg_head;
    struct hsr_priv *hsr;
    void *pos;
    unsigned char addr[ETH_ALEN];
    int res;

    if (!info)
        goto invalid;

    na = info->attrs[HSR_A_IFINDEX];
    if (!na)
        goto invalid;

    hsr_dev = __dev_get_by_index(genl_info_net(info),
                                 nla_get_u32(info->attrs[HSR_A_IFINDEX]));
    if (!hsr_dev)
        goto invalid;
    if (!is_hsr_master(hsr_dev))
        goto invalid;


    /* Send reply */

    skb_out = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
    if (!skb_out) {
        res = -ENOMEM;
        goto fail;
    }

    msg_head = genlmsg_put(skb_out, NETLINK_CB(skb_in).portid,
                           info->snd_seq, &hsr_genl_family, 0,
                           HSR_C_SET_NODE_LIST);
    if (!msg_head) {
        res = -ENOMEM;
        goto nla_put_failure;
    }

    res = nla_put_u32(skb_out, HSR_A_IFINDEX, hsr_dev->ifindex);
    if (res < 0)
        goto nla_put_failure;

    hsr = netdev_priv(hsr_dev);

    rcu_read_lock();
    pos = hsr_get_next_node(hsr, NULL, addr);
    while (pos) {
        res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr);
        if (res < 0) {
            rcu_read_unlock();
            goto nla_put_failure;
        }
        pos = hsr_get_next_node(hsr, pos, addr);
    }
    rcu_read_unlock();

    genlmsg_end(skb_out, msg_head);
    genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid);

    return 0;

invalid:
    netlink_ack(skb_in, nlmsg_hdr(skb_in), -EINVAL);
    return 0;

nla_put_failure:
    kfree_skb(skb_out);
    /* Fall through */

fail:
    return res;
}
示例#10
0
int cap_netlink_send (struct sk_buff *skb)
{
	NETLINK_CB (skb).eff_cap = current->cap_effective;
	return 0;
}
static int
netlink_trans_request(struct sk_buff *in_skb, struct genl_info *info)
{
    char *buf;
    unsigned int len;
    uint32_t multi_flag;
    struct nlmsghdr *rep, *nlh = info->nlhdr;
    struct genlmsghdr *genlh;
    struct nlattr **aap = info->attrs;
    struct nlattr *nla;
    struct vr_message request, *response;
    struct sk_buff *skb;

    if (!aap || !(nla = aap[NL_ATTR_VR_MESSAGE_PROTOCOL]))
        return -EINVAL;

    request.vr_message_buf = nla_data(nla);
    request.vr_message_len = nla_len(nla);

    vr_message_request(&request);

    multi_flag = 0;
    while ((response = vr_message_dequeue_response())) {
        if ((multi_flag == 0) && (!vr_response_queue_empty()))
            multi_flag = NLM_F_MULTI;

        buf = response->vr_message_buf;
        skb = netlink_skb(buf);
        if (!skb)
            continue;

        len = response->vr_message_len;
        len += GENL_HDRLEN + NLA_HDRLEN;
        len = NLMSG_ALIGN(len);

        rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
                        nlh->nlmsg_type, len, multi_flag);
        genlh = nlmsg_data(rep);
        memcpy(genlh, info->genlhdr, sizeof(*genlh));

        nla = (struct nlattr *)((char *)genlh + GENL_HDRLEN);
        nla->nla_len = response->vr_message_len;
        nla->nla_type = NL_ATTR_VR_MESSAGE_PROTOCOL;

        netlink_unicast(in_skb->sk, skb,
                        NETLINK_CB(in_skb).pid, MSG_DONTWAIT);

        response->vr_message_buf = NULL;
        vr_message_free(response);
    }

    if (multi_flag) {
        skb = alloc_skb(NLMSG_HDRLEN, GFP_ATOMIC);
        if (!skb)
            return 0;

        __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
                                                NLMSG_DONE, 0, 0);
        netlink_unicast(in_skb->sk, skb,
                        NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
    }


    return 0;
}
示例#12
0
static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
	struct net *net = sock_net(skb->sk);
	struct net_device *netdev;
	struct dcbmsg  *dcb = (struct dcbmsg *)NLMSG_DATA(nlh);
	struct nlattr *tb[DCB_ATTR_MAX + 1];
	u32 pid = skb ? NETLINK_CB(skb).pid : 0;
	int ret = -EINVAL;

	if (net != &init_net)
		return -EINVAL;

	ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
			  dcbnl_rtnl_policy);
	if (ret < 0)
		return ret;

	if (!tb[DCB_ATTR_IFNAME])
		return -EINVAL;

	netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
	if (!netdev)
		return -EINVAL;

	if (!netdev->dcbnl_ops)
		goto errout;

	switch (dcb->cmd) {
	case DCB_CMD_GSTATE:
		ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,
		                     nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PFC_GCFG:
		ret = dcbnl_getpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
		                      nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_GPERM_HWADDR:
		ret = dcbnl_getperm_hwaddr(netdev, tb, pid, nlh->nlmsg_seq,
		                           nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PGTX_GCFG:
		ret = dcbnl_pgtx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
		                        nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PGRX_GCFG:
		ret = dcbnl_pgrx_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
		                        nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_BCN_GCFG:
		ret = dcbnl_bcn_getcfg(netdev, tb, pid, nlh->nlmsg_seq,
		                       nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_SSTATE:
		ret = dcbnl_setstate(netdev, tb, pid, nlh->nlmsg_seq,
		                     nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PFC_SCFG:
		ret = dcbnl_setpfccfg(netdev, tb, pid, nlh->nlmsg_seq,
		                      nlh->nlmsg_flags);
		goto out;

	case DCB_CMD_SET_ALL:
		ret = dcbnl_setall(netdev, tb, pid, nlh->nlmsg_seq,
		                   nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PGTX_SCFG:
		ret = dcbnl_pgtx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
		                        nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PGRX_SCFG:
		ret = dcbnl_pgrx_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
		                        nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_GCAP:
		ret = dcbnl_getcap(netdev, tb, pid, nlh->nlmsg_seq,
		                   nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_GNUMTCS:
		ret = dcbnl_getnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
		                      nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_SNUMTCS:
		ret = dcbnl_setnumtcs(netdev, tb, pid, nlh->nlmsg_seq,
		                      nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PFC_GSTATE:
		ret = dcbnl_getpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
		                        nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_PFC_SSTATE:
		ret = dcbnl_setpfcstate(netdev, tb, pid, nlh->nlmsg_seq,
		                        nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_BCN_SCFG:
		ret = dcbnl_bcn_setcfg(netdev, tb, pid, nlh->nlmsg_seq,
		                       nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_GAPP:
		ret = dcbnl_getapp(netdev, tb, pid, nlh->nlmsg_seq,
		                   nlh->nlmsg_flags);
		goto out;
	case DCB_CMD_SAPP:
		ret = dcbnl_setapp(netdev, tb, pid, nlh->nlmsg_seq,
		                   nlh->nlmsg_flags);
		goto out;
	default:
		goto errout;
	}
errout:
	ret = -EINVAL;
out:
	dev_put(netdev);
	return ret;
}
示例#13
0
int cap_netlink_recv(struct sk_buff *skb, int cap)
{
	if (!cap_raised(NETLINK_CB(skb).eff_cap, cap))
		return -EPERM;
	return 0;
}
示例#14
0
int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
{
	NETLINK_CB(skb).eff_cap = current_cap();
	return 0;
}
//---------------------------------------------------------------------------
int nasmt_netlink_send(unsigned char *data_buffer, unsigned int data_length, int destination)
{
  //---------------------------------------------------------------------------
  struct sk_buff *nl_skb;
  struct nlmsghdr *nlh;
  int status;
  // Start debug information
#ifdef NETLINK_DEBUG
  printk("nasmt_netlink_send - begin \n");
#endif

  if (!data_buffer) {
    printk("nasmt_netlink_send - ERROR - input parameter data is NULL \n");
    return(0);
  }

  if (!nas_nl_sk || !nas_rrcnl_sk) {
    printk("nasmt_netlink_send - ERROR - socket is NULL\n");
    return(0);
  }

  // End debug information

  nl_skb = alloc_skb(NLMSG_SPACE(data_length),GFP_ATOMIC);

  if (!nl_skb) {
    printk("nasmt_netlink_send - ERROR - could not allocate skbuffer\n");
    return(0);
  }

  nlh = (struct nlmsghdr *)nl_skb->data;

  //  printk("nasmt_netlink_send Sending %d bytes (%d)\n",data_length,NLMSG_SPACE(data_length));
  skb_put(nl_skb, NLMSG_SPACE(data_length));
  memcpy(NLMSG_DATA(nlh), data_buffer, data_length);
  nlh->nlmsg_len = NLMSG_SPACE(data_length);

  nlh->nlmsg_pid = 0;      /* from kernel */
  NETLINK_CB(nl_skb).pid = 0;

  // destination 0 = PDCP, 1 = RRC
  if (!destination) {
#ifdef NETLINK_DEBUG
    printk("nasmt_netlink_send - nl_skb %p, nl_sk %p, nlh %p, nlh->nlmsg_len %d\n", nl_skb, nas_nl_sk, nlh, nlh->nlmsg_len);
#endif //DEBUG_NETLINK
    status = netlink_unicast(nas_nl_sk, nl_skb, NL_DEST_PID, MSG_DONTWAIT);
  } else {
#ifdef NAS_DEBUG_RRCNL
    printk("nasmt_rrcnl_send - nl_skb %p, nas_rrcnl_sk %p, nlh %p, nlh->nlmsg_len %d\n", nl_skb, nas_rrcnl_sk, nlh, nlh->nlmsg_len);
#endif //NAS_DEBUG_RRCNL
    status = netlink_unicast(nas_rrcnl_sk, nl_skb, NL_DEST_RRC_PID, MSG_DONTWAIT);
  }

  if (status < 0) {
    printk("nasmt_netlink_send - SEND status is %d\n",status);
    return(0);
  } else {
#ifdef NETLINK_DEBUG
    printk("nasmt_netlink_send - SEND status is %d, data_length %d\n",status, data_length);
#endif
    return data_length;
  }
}
示例#16
0
static struct sk_buff *netlink_build_message(ipq_queue_element_t *e, int *errp)
{
	unsigned char *old_tail;
	size_t size = 0;
	size_t data_len = 0;
	struct sk_buff *skb;
	ipq_packet_msg_t *pm;
	struct nlmsghdr *nlh;

	switch (nlq->peer.copy_mode) {
		size_t copy_range;

		case IPQ_COPY_META:
			size = NLMSG_SPACE(sizeof(*pm));
			data_len = 0;
			break;
		case IPQ_COPY_PACKET:
			copy_range = nlq->peer.copy_range;
			if (copy_range == 0 || copy_range > e->skb->len)
				data_len = e->skb->len;
			else
				data_len = copy_range;
			size = NLMSG_SPACE(sizeof(*pm) + data_len);
			
			break;
		case IPQ_COPY_NONE:
		default:
			*errp = -EINVAL;
			return NULL;
	}
	skb = alloc_skb(size, GFP_ATOMIC);
	if (!skb)
		goto nlmsg_failure;
	old_tail = skb->tail;
	nlh = NLMSG_PUT(skb, 0, 0, IPQM_PACKET, size - sizeof(*nlh));
	pm = NLMSG_DATA(nlh);
	memset(pm, 0, sizeof(*pm));
	pm->packet_id = (unsigned long )e;
	pm->data_len = data_len;
	pm->timestamp_sec = e->skb->stamp.tv_sec;
	pm->timestamp_usec = e->skb->stamp.tv_usec;
	pm->mark = e->skb->nfmark;
	pm->hook = e->info->hook;
	if (e->info->indev) strcpy(pm->indev_name, e->info->indev->name);
	else pm->indev_name[0] = '\0';
	if (e->info->outdev) strcpy(pm->outdev_name, e->info->outdev->name);
	else pm->outdev_name[0] = '\0';
	pm->hw_protocol = e->skb->protocol;
	if (e->info->indev && e->skb->dev) {
		pm->hw_type = e->skb->dev->type;
		if (e->skb->dev->hard_header_parse)
			pm->hw_addrlen =
				e->skb->dev->hard_header_parse(e->skb,
				                               pm->hw_addr);
	}
	if (data_len)
		memcpy(pm->payload, e->skb->data, data_len);
	nlh->nlmsg_len = skb->tail - old_tail;
	NETLINK_CB(skb).dst_groups = 0;
	return skb;
nlmsg_failure:
	if (skb)
		kfree_skb(skb);
	*errp = 0;
	printk(KERN_ERR "ip_queue: error creating netlink message\n");
	return NULL;
}
示例#17
0
static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
				 int type, u32 pid, u32 seq, u32 change, 
				 unsigned int flags)
{
	struct ifinfomsg *r;
	struct nlmsghdr  *nlh;
	unsigned char	 *b = skb->tail;

	nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags);
	r = NLMSG_DATA(nlh);
	r->ifi_family = AF_UNSPEC;
	r->__ifi_pad = 0;
	r->ifi_type = dev->type;
	r->ifi_index = dev->ifindex;
	r->ifi_flags = dev_get_flags(dev);
	r->ifi_change = change;

	RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name);

	if (1) {
		u32 txqlen = dev->tx_queue_len;
		RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen);
	}

	if (1) {
		u32 weight = dev->weight;
		RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight);
	}

	if (1) {
		u8 operstate = netif_running(dev)?dev->operstate:IF_OPER_DOWN;
		u8 link_mode = dev->link_mode;
		RTA_PUT(skb, IFLA_OPERSTATE, sizeof(operstate), &operstate);
		RTA_PUT(skb, IFLA_LINKMODE, sizeof(link_mode), &link_mode);
	}

	if (1) {
		struct rtnl_link_ifmap map = {
			.mem_start   = dev->mem_start,
			.mem_end     = dev->mem_end,
			.base_addr   = dev->base_addr,
			.irq         = dev->irq,
			.dma         = dev->dma,
			.port        = dev->if_port,
		};
		RTA_PUT(skb, IFLA_MAP, sizeof(map), &map);
	}

	if (dev->addr_len) {
		RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr);
		RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast);
	}

	if (1) {
		u32 mtu = dev->mtu;
		RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu);
	}

	if (dev->ifindex != dev->iflink) {
		u32 iflink = dev->iflink;
		RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink);
	}

	if (dev->qdisc_sleeping)
		RTA_PUT(skb, IFLA_QDISC,
			strlen(dev->qdisc_sleeping->ops->id) + 1,
			dev->qdisc_sleeping->ops->id);
	
	if (dev->master) {
		u32 master = dev->master->ifindex;
		RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master);
	}

	if (dev->get_stats) {
		unsigned long *stats = (unsigned long*)dev->get_stats(dev);
		if (stats) {
			struct rtattr  *a;
			__u32	       *s;
			int		i;
			int		n = sizeof(struct rtnl_link_stats)/4;

			a = __RTA_PUT(skb, IFLA_STATS, n*4);
			s = RTA_DATA(a);
			for (i=0; i<n; i++)
				s[i] = stats[i];
		}
	}
	nlh->nlmsg_len = skb->tail - b;
	return skb->len;

nlmsg_failure:
rtattr_failure:
	skb_trim(skb, b - skb->data);
	return -1;
}

static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
	int idx;
	int s_idx = cb->args[0];
	struct net_device *dev;

	read_lock(&dev_base_lock);
	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
		if (idx < s_idx)
			continue;
		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
					  NETLINK_CB(cb->skb).pid,
					  cb->nlh->nlmsg_seq, 0,
					  NLM_F_MULTI) <= 0)
			break;
	}
	read_unlock(&dev_base_lock);
	cb->args[0] = idx;

	return skb->len;
}
static int
itson_rcv_msg(struct sk_buff *skb_2, struct genl_info *info)
{
	struct nlattr *na;
	struct msgInfo minfo;
	int rc = 0;
	void *msg;
	int index;

	if (info == NULL) {
		rc = -EINVAL;
		goto rcv_msg_err;
	}
	index = info->genlhdr->cmd;

	/* Ignore control command */
	if (index < CTRL_CMD_MAX) {
		INFO("Received control msg %d, skipping\n", index);
		return 0;
	}

	// Ignore out-of-range commands (not ours, so print an error).
	if (index < ITSON_CMD_0 || index > ITSON_CMD_MAX) {
		ERR("Received out-of-range netlink message %d, skipping\n", index);
		return 0;
	}


	//INFO("%s cmd %d", __func__, index);
	na = info->attrs[index];
	if (na == NULL) {
		printk("no info->attrs %i\n", index);
		rc = -EINVAL;
		goto rcv_msg_err;
	}

	msg = nla_data(na);
	if (msg == NULL) {
		printk("error while receiving data\n");
		rc = -EINVAL;
		goto rcv_msg_err;

	}

	//INFO("cmd %d len %d\n", index, na->nla_len);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
	minfo.pid = info->snd_portid;
#else
	minfo.pid = info->snd_pid;
#endif
	minfo.uid = NETLINK_CB(skb_2).creds.uid;
	minfo.gid = NETLINK_CB(skb_2).creds.gid;
	if (msgHandlerList[index]) {
		rc = msgHandlerList[index](msg, nla_len(na), &minfo);
	} else {
		ERR("No handler for found cmd %d", index);
		rc = -EINVAL;
		goto rcv_msg_err;
	}


rcv_msg_err:
	return rc;
}
VOS_INT DMS_NLK_Send(
    DMS_NLK_PHY_BEAR_ENUM_UINT32        enPhyBear,
    DMS_NLK_MSG_TYPE_ENUM_UINT32        enMsgType,
    VOS_UINT8                          *pucData,
    VOS_UINT32                          ulLength
)
{
    struct sk_buff                     *pstSkb      = VOS_NULL_PTR;
    struct nlmsghdr                    *pstNlkHdr   = VOS_NULL_PTR;
    DMS_NLK_PAYLOAD_STRU               *pstPlayload = VOS_NULL_PTR;
    VOS_UINT                            ulMsgSize;
    VOS_UINT                            ulPayloadSize;
    VOS_INT                             lRet;

    DMS_DBG_NLK_DL_TOTAL_MSG_NUM(1);

    /* 检查 netlink socket */
    if (VOS_NULL_PTR == DMS_GET_NLK_SOCK())
    {
        DMS_DBG_NLK_DL_ERR_SOCK_MSG_NUM(1);
        return -EIO;
    }

    /* 检查物理承载状态 */
    if (DMS_NLK_INVALID_PID == DMS_GET_NLK_PHY_PID(enPhyBear))
    {
        DMS_DBG_NLK_DL_ERR_PID_MSG_NUM(1);
        return -EINVAL;
    }

    /* 申请 netlink 消息 */
    ulPayloadSize = sizeof(DMS_NLK_PAYLOAD_STRU) + ulLength;
    ulMsgSize = NLMSG_SPACE(ulPayloadSize);

    pstSkb = nlmsg_new(ulPayloadSize, GFP_ATOMIC);
    if (VOS_NULL_PTR == pstSkb)
    {
        DMS_DBG_NLK_DL_ALLOC_MSG_FAIL_NUM(1);
        return -ENOBUFS;
    }

    /* 填充 netlink 消息头 */
    /* Use "ulMsgSize - sizeof(*pstNlkHdr)" here (incluing align pads) */
    pstNlkHdr = nlmsg_put(pstSkb, 0, 0, (VOS_INT)enMsgType,
                    (VOS_INT)(ulMsgSize - sizeof(struct nlmsghdr)), 0);
    if (VOS_NULL_PTR == pstNlkHdr)
    {
        kfree_skb(pstSkb);
        DMS_DBG_NLK_DL_PUT_MSG_FAIL_NUM(1);
        return -EMSGSIZE;
    }

    /* 填充 netlink 消息接收PID */
    /*lint -e545*/
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) || (VOS_OS_VER == VOS_WIN32))
    NETLINK_CB(pstSkb).portid = DMS_GET_NLK_PHY_PID(enPhyBear);
#else
    NETLINK_CB(pstSkb).pid = DMS_GET_NLK_PHY_PID(enPhyBear);
#endif
    NETLINK_CB(pstSkb).dst_group = 0;
    /*lint +e545*/

    /* 填充 netlink 消息内容 */
    pstPlayload = nlmsg_data(pstNlkHdr);
    pstPlayload->ulLength = ulLength;

    memcpy(pstPlayload->aucData, pucData, ulLength);

    /* 发送 netlink 消息 */
    /*lint -e545*/
#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) || (VOS_OS_VER == VOS_WIN32))
    lRet = netlink_unicast(DMS_GET_NLK_SOCK(), pstSkb, NETLINK_CB(pstSkb).portid, 0);
#else
    lRet = netlink_unicast(DMS_GET_NLK_SOCK(), pstSkb, NETLINK_CB(pstSkb).pid, 0);
#endif

    /*lint +e545*/
    if (lRet < 0)
    {
        DMS_DBG_NLK_DL_UNICAST_MSG_FAIL_NUM(1);
        return lRet;
    }

    DMS_DBG_NLK_DL_UNICAST_MSG_SUCC_NUM(1);
    return 0;
}
示例#20
0
static int dummy_netlink_recv (struct sk_buff *skb)
{
	if (!cap_raised (NETLINK_CB (skb).eff_cap, CAP_NET_ADMIN))
		return -EPERM;
	return 0;
}
示例#21
0
static int
tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
{
	struct net *net = sock_net(skb->sk);
	struct nlmsghdr *nlh;
	unsigned char *b = skb_tail_pointer(skb);
	struct nlattr *nest;
	struct tc_action_ops *a_o;
	struct tc_action a;
	int ret = 0;
	struct tcamsg *t = (struct tcamsg *) NLMSG_DATA(cb->nlh);
	struct nlattr *kind = find_dump_kind(cb->nlh);

	if (net != &init_net)
		return 0;

	if (kind == NULL) {
		printk("tc_dump_action: action bad kind\n");
		return 0;
	}

	a_o = tc_lookup_action(kind);
	if (a_o == NULL) {
		return 0;
	}

	memset(&a, 0, sizeof(struct tc_action));
	a.ops = a_o;

	if (a_o->walk == NULL) {
		printk("tc_dump_action: %s !capable of dumping table\n", a_o->kind);
		goto nla_put_failure;
	}

	nlh = NLMSG_PUT(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq,
			cb->nlh->nlmsg_type, sizeof(*t));
	t = NLMSG_DATA(nlh);
	t->tca_family = AF_UNSPEC;
	t->tca__pad1 = 0;
	t->tca__pad2 = 0;

	nest = nla_nest_start(skb, TCA_ACT_TAB);
	if (nest == NULL)
		goto nla_put_failure;

	ret = a_o->walk(skb, cb, RTM_GETACTION, &a);
	if (ret < 0)
		goto nla_put_failure;

	if (ret > 0) {
		nla_nest_end(skb, nest);
		ret = skb->len;
	} else
		nla_nest_cancel(skb, nest);

	nlh->nlmsg_len = skb_tail_pointer(skb) - b;
	if (NETLINK_CB(cb->skb).pid && ret)
		nlh->nlmsg_flags |= NLM_F_MULTI;
	module_put(a_o->owner);
	return skb->len;

nla_put_failure:
nlmsg_failure:
	module_put(a_o->owner);
	nlmsg_trim(skb, b);
	return skb->len;
}
示例#22
0
static int
nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb,
		const struct nlmsghdr *nlh, const struct nlattr * const tb[])
{
	int ret = 0, target;
	struct nfgenmsg *nfmsg;
	const char *fmt;
	const char *name;
	u32 rev;
	struct sk_buff *skb2;

	if (tb[NFTA_COMPAT_NAME] == NULL ||
	    tb[NFTA_COMPAT_REV] == NULL ||
	    tb[NFTA_COMPAT_TYPE] == NULL)
		return -EINVAL;

	name = nla_data(tb[NFTA_COMPAT_NAME]);
	rev = ntohl(nla_get_be32(tb[NFTA_COMPAT_REV]));
	target = ntohl(nla_get_be32(tb[NFTA_COMPAT_TYPE]));

	nfmsg = nlmsg_data(nlh);

	switch(nfmsg->nfgen_family) {
	case AF_INET:
		fmt = "ipt_%s";
		break;
	case AF_INET6:
		fmt = "ip6t_%s";
		break;
	default:
		pr_err("nft_compat: unsupported protocol %d\n",
			nfmsg->nfgen_family);
		return -EINVAL;
	}

	try_then_request_module(xt_find_revision(nfmsg->nfgen_family, name,
						 rev, target, &ret),
						 fmt, name);

	if (ret < 0)
		return ret;

	skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (skb2 == NULL)
		return -ENOMEM;

	/* include the best revision for this extension in the message */
	if (nfnl_compat_fill_info(skb2, NETLINK_CB(skb).portid,
				  nlh->nlmsg_seq,
				  NFNL_MSG_TYPE(nlh->nlmsg_type),
				  NFNL_MSG_COMPAT_GET,
				  nfmsg->nfgen_family,
				  name, ret, target) <= 0) {
		kfree_skb(skb2);
		return -ENOSPC;
	}

	ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid,
				MSG_DONTWAIT);
	if (ret > 0)
		ret = 0;

	return ret == -EAGAIN ? -ENOBUFS : ret;
}