OSDN Git Service

4f4113d99183cff6297427bf91d85a83cd6c2c57
[immortalwrt/immortalwrt.git] / package / kernel / fast-classifier / src / userspace_example.c
1 /*
2  * Copyright (c) 2013,2016 The Linux Foundation. All rights reserved.
3  * Permission to use, copy, modify, and/or distribute this software for
4  * any purpose with or without fee is hereby granted, provided that the
5  * above copyright notice and this permission notice appear in all copies.
6  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
7  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
8  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
9  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
10  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
11  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
12  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
13  */
14
15 #include <netlink/genl/genl.h>
16 #include <netlink/genl/ctrl.h>
17 #include <errno.h>
18 #include <stdio.h>
19 #include <arpa/inet.h>
20
21 #include <fast-classifier.h>
22
23 static struct nl_sock *sock;
24 static struct nl_sock *sock_event;
25 static int family;
26 static int grp_id;
27
28 static struct nla_policy fast_classifier_genl_policy[FAST_CLASSIFIER_A_MAX + 1] = {
29         [FAST_CLASSIFIER_A_TUPLE] = { .type = NLA_UNSPEC },
30 };
31
32 void dump_fc_tuple(struct fast_classifier_tuple *fc_msg)
33 {
34         char src_str[INET_ADDRSTRLEN];
35         char dst_str[INET_ADDRSTRLEN];
36
37         printf("TUPLE: %d, %s, %s, %d, %d"
38                         " SMAC=%02x:%02x:%02x:%02x:%02x:%02x",
39                         " DMAC=%02x:%02x:%02x:%02x:%02x:%02x\n",
40                                 fc_msg->proto,
41                                 inet_ntop(AF_INET,
42                                           &fc_msg->src_saddr.in.s_addr,
43                                           src_str,
44                                           INET_ADDRSTRLEN),
45                                 inet_ntop(AF_INET,
46                                           &fc_msg->dst_saddr.in.s_addr,
47                                           dst_str,
48                                           INET_ADDRSTRLEN),
49                                 fc_msg->sport, fc_msg->dport,
50                                 fc_msg->smac[0], fc_msg->smac[1], fc_msg->smac[2],
51                                 fc_msg->smac[3], fc_msg->smac[4], fc_msg->smac[5],
52                                 fc_msg->dmac[0], fc_msg->dmac[1], fc_msg->dmac[2],
53                                 fc_msg->dmac[3], fc_msg->dmac[4], fc_msg->dmac[5]);
54 }
55
56 static int parse_cb(struct nl_msg *msg, void *arg)
57 {
58         struct nlmsghdr *nlh = nlmsg_hdr(msg);
59         struct genlmsghdr *gnlh = nlmsg_data(nlh);
60         struct nlattr *attrs[FAST_CLASSIFIER_A_MAX];
61
62         genlmsg_parse(nlh, 0, attrs, FAST_CLASSIFIER_A_MAX, fast_classifier_genl_policy);
63
64         switch (gnlh->cmd) {
65         case FAST_CLASSIFIER_C_OFFLOADED:
66                 printf("Got a offloaded message\n");
67                 dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE]));
68                 return NL_OK;
69         case FAST_CLASSIFIER_C_DONE:
70                 printf("Got a done message\n");
71                 dump_fc_tuple(nla_data(attrs[FAST_CLASSIFIER_A_TUPLE]));
72                 return NL_OK;
73         }
74
75         return NL_SKIP;
76 }
77
78 int fast_classifier_init(void)
79 {
80         int err;
81
82         sock = nl_socket_alloc();
83         if (!sock) {
84                 printf("Unable to allocation socket.\n");
85                 return -1;
86         }
87         genl_connect(sock);
88
89         sock_event = nl_socket_alloc();
90         if (!sock_event) {
91                 nl_close(sock);
92                 nl_socket_free(sock);
93                 printf("Unable to allocation socket.\n");
94                 return -1;
95         }
96         genl_connect(sock_event);
97
98         family = genl_ctrl_resolve(sock, FAST_CLASSIFIER_GENL_NAME);
99         if (family < 0) {
100                 nl_close(sock_event);
101                 nl_close(sock);
102                 nl_socket_free(sock);
103                 nl_socket_free(sock_event);
104                 printf("Unable to resolve family\n");
105                 return -1;
106         }
107
108         grp_id = genl_ctrl_resolve_grp(sock, FAST_CLASSIFIER_GENL_NAME,
109                                        FAST_CLASSIFIER_GENL_MCGRP);
110         if (grp_id < 0) {
111                 printf("Unable to resolve mcast group\n");
112                 return -1;
113         }
114
115         err = nl_socket_add_membership(sock_event, grp_id);
116         if (err < 0) {
117                 printf("Unable to add membership\n");
118                 return -1;
119         }
120
121         nl_socket_disable_seq_check(sock_event);
122         nl_socket_modify_cb(sock_event, NL_CB_VALID, NL_CB_CUSTOM, parse_cb, NULL);
123
124         return 0;
125 }
126
127 void fast_classifier_close(void)
128 {
129         nl_close(sock_event);
130         nl_close(sock);
131         nl_socket_free(sock_event);
132         nl_socket_free(sock);
133 }
134
135 void fast_classifier_ipv4_offload(unsigned char proto, unsigned long src_saddr,
136                                   unsigned long dst_saddr, unsigned short sport,
137                                   unsigned short dport)
138 {
139         struct nl_msg *msg;
140         int ret;
141 #ifdef DEBUG
142         char src_str[INET_ADDRSTRLEN];
143         char dst_str[INET_ADDRSTRLEN];
144 #endif
145         struct fast_classifier_tuple fc_msg;
146
147 #ifdef DEBUG
148         printf("DEBUG: would offload: %d, %s, %s, %d, %d\n", proto,
149                inet_ntop(AF_INET, &src_saddr,  src_str, INET_ADDRSTRLEN),
150                inet_ntop(AF_INET, &dst_saddr,  dst_str, INET_ADDRSTRLEN),
151                sport, dport);
152 #endif
153
154         fc_msg.proto = proto;
155         fc_msg.src_saddr.in.s_addr = src_saddr;
156         fc_msg.dst_saddr.in.s_addr = dst_saddr;
157         fc_msg.sport = sport;
158         fc_msg.dport = dport;
159         fc_msg.smac[0] = 'a';
160         fc_msg.smac[1] = 'b';
161         fc_msg.smac[2] = 'c';
162         fc_msg.smac[3] = 'd';
163         fc_msg.smac[4] = 'e';
164         fc_msg.smac[5] = 'f';
165         fc_msg.dmac[0] = 'f';
166         fc_msg.dmac[1] = 'e';
167         fc_msg.dmac[2] = 'd';
168         fc_msg.dmac[3] = 'c';
169         fc_msg.dmac[4] = 'b';
170         fc_msg.dmac[5] = 'a';
171
172         if (fast_classifier_init() < 0) {
173                 printf("Unable to init generic netlink\n");
174                 exit(1);
175         }
176
177         msg = nlmsg_alloc();
178         if (!msg) {
179                 nl_socket_free(sock);
180                 printf("Unable to allocate message\n");
181                 return;
182         }
183
184         genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family,
185                     FAST_CLASSIFIER_GENL_HDRSIZE, NLM_F_REQUEST,
186                     FAST_CLASSIFIER_C_OFFLOAD, FAST_CLASSIFIER_GENL_VERSION);
187         nla_put(msg, 1, sizeof(fc_msg), &fc_msg);
188
189         ret = nl_send_auto_complete(sock, msg);
190
191         nlmsg_free(msg);
192         if (ret < 0) {
193                 printf("nlmsg_free failed");
194                 nl_close(sock);
195                 nl_socket_free(sock);
196                 return;
197         }
198
199         ret = nl_wait_for_ack(sock);
200         if (ret < 0) {
201                 printf("wait for ack failed");
202                 nl_close(sock);
203                 nl_socket_free(sock);
204                 return;
205         }
206 }
207
208 void fast_classifier_listen_for_messages(void)
209 {
210         printf("waiting for netlink events\n");
211
212         while (1) {
213                 nl_recvmsgs_default(sock_event);
214         }
215 }
216
217 int main(int argc, char *argv[])
218 {
219         if (fast_classifier_init() < 0) {
220                 printf("Unable to init generic netlink\n");
221                 exit(1);
222         }
223
224         fast_classifier_ipv4_offload('a', 0, 0, 0, 0);
225
226         /* this never returns */
227         fast_classifier_listen_for_messages();
228
229         fast_classifier_close();
230
231         return 0;
232 }