File: netl.c

package info (click to toggle)
pyroute2 0.8.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,704 kB
  • sloc: python: 50,245; makefile: 280; javascript: 183; ansic: 81; sh: 44; awk: 17
file content (130 lines) | stat: -rw-r--r-- 3,561 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
 * Generic netlink sample -- kernel module
 * Use `make` to compile and `insmod` to load the module
 *
 * Sergiy Lozovsky <sergiy.lozovsky@gmail.com>
 * Peter V. Saveliev <peter@svinota.eu>
 *
 * Requires kernel 4.10+
 */
#include <linux/module.h>       /* Needed by all modules */
#include <linux/kernel.h>       /* Needed for KERN_INFO */
#include <linux/init.h>         /* Needed for the macros */
#include <net/genetlink.h>

/* attributes (variables): the index in this enum is used as a reference for the type,
 *             userspace application has to indicate the corresponding type
 *             the policy is used for security considerations
 */
enum {
    EXMPL_NLA_UNSPEC,
    EXMPL_NLA_DATA,
    EXMPL_NLA_LEN,
    __EXMPL_NLA_MAX,
};
/* ... and the same for commands
 */
enum {
    EXMPL_CMD_UNSPEC,
    EXMPL_CMD_MSG,
};

/* attribute policy: defines which attribute has which type (e.g int, char * etc)
 * possible values defined in net/netlink.h
 */
static struct nla_policy exmpl_genl_policy[__EXMPL_NLA_MAX] = {
        [EXMPL_NLA_DATA] = { .type = NLA_NUL_STRING },
        [EXMPL_NLA_LEN] = { .type = NLA_U32 },
};

#define VERSION_NR 1
static struct genl_family exmpl_gnl_family;

static int get_length(struct sk_buff *request, struct genl_info *info)
{
    struct sk_buff *reply;
    char *buffer;
    void *msg_head;

    if (info == NULL)
        return -EINVAL;

    if (!info->attrs[EXMPL_NLA_DATA])
        return -EINVAL;

    /* get the data */
    buffer = nla_data(info->attrs[EXMPL_NLA_DATA]);

    /* send a message back*/
    /* allocate some memory, since the size is not yet known use NLMSG_GOODSIZE*/
    reply = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
    if (reply == NULL)
        return -ENOMEM;

    /* start the message */
    msg_head = genlmsg_put_reply(reply, info, &exmpl_gnl_family, 0, info->genlhdr->cmd);
    if (msg_head == NULL) {
        return -ENOMEM;
    }

    /* add a EXMPL_LEN attribute -- report the data length */
    if (0 != nla_put_u32(reply, EXMPL_NLA_LEN, strlen(buffer)))
        return -EINVAL;

    /* finalize the message */
    genlmsg_end(reply, msg_head);

    /* send the message back */
    if (0 != genlmsg_reply(reply, info))
        return -EINVAL;

    return 0;
}

/* commands: mapping between commands and actual functions*/
static const struct genl_ops exmpl_gnl_ops_echo[] = {
    {
        .cmd = EXMPL_CMD_MSG,
        .policy = exmpl_genl_policy,
        .doit = get_length,
    },
};

/* family definition */
static struct genl_family exmpl_gnl_family __ro_after_init = {
        .name = "EXMPL_GENL",           //the name of this family, used by userspace application
        .version = VERSION_NR,          //version number
        .maxattr = __EXMPL_NLA_MAX - 1,
        .module = THIS_MODULE,
        .ops = exmpl_gnl_ops_echo,
        .n_ops = ARRAY_SIZE(exmpl_gnl_ops_echo),
};



static int __init exmpl_gnl_init(void)
{
        int rc;
        rc = genl_register_family(&exmpl_gnl_family);
        if (rc != 0) {
            printk(KERN_INFO "rkmod: genl_register_family failed %d\n", rc);
            return 1;
        }
        printk(KERN_INFO "Generic netlink example loaded, protocol version %d\n", VERSION_NR);
        return 0;
}

static void __exit exmpl_gnl_exit(void)
{
        int ret;
        /*unregister the family*/
        ret = genl_unregister_family(&exmpl_gnl_family);
        if(ret !=0){
                printk("unregister family %i\n",ret);
        }
}

module_init(exmpl_gnl_init);
module_exit(exmpl_gnl_exit);

MODULE_LICENSE("GPL");