]>
Commit | Line | Data |
---|---|---|
a6c5c952 GN |
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | ||
3 | #include <stdio.h> | |
d44bcd2f SH |
4 | #include <linux/if_ether.h> |
5 | #include <linux/if_link.h> | |
6 | #include <linux/netlink.h> | |
7 | #include <linux/rtnetlink.h> | |
a6c5c952 GN |
8 | |
9 | #include "libnetlink.h" | |
a6c5c952 GN |
10 | #include "rt_names.h" |
11 | #include "utils.h" | |
12 | #include "ip_common.h" | |
13 | #include "json_print.h" | |
14 | ||
15 | #define BAREUDP_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0) | |
16 | ||
17 | static void print_explain(FILE *f) | |
18 | { | |
19 | fprintf(f, | |
20 | "Usage: ... bareudp dstport PORT\n" | |
21 | " ethertype PROTO\n" | |
22 | " [ srcportmin PORT ]\n" | |
23 | " [ [no]multiproto ]\n" | |
24 | "\n" | |
25 | "Where: PORT := 0-65535\n" | |
26 | " PROTO := NUMBER | ip | mpls\n" | |
27 | " SRCPORTMIN := 0-65535\n" | |
28 | ); | |
29 | } | |
30 | ||
31 | static void explain(void) | |
32 | { | |
33 | print_explain(stderr); | |
34 | } | |
35 | ||
36 | static void check_duparg(__u64 *attrs, int type, const char *key, | |
37 | const char *argv) | |
38 | { | |
39 | if (!BAREUDP_ATTRSET(*attrs, type)) { | |
40 | *attrs |= (1L << type); | |
41 | return; | |
42 | } | |
43 | duparg2(key, argv); | |
44 | } | |
45 | ||
46 | static int bareudp_parse_opt(struct link_util *lu, int argc, char **argv, | |
47 | struct nlmsghdr *n) | |
48 | { | |
49 | bool multiproto = false; | |
50 | __u16 srcportmin = 0; | |
51 | __be16 ethertype = 0; | |
52 | __be16 dstport = 0; | |
53 | __u64 attrs = 0; | |
54 | ||
55 | while (argc > 0) { | |
56 | if (matches(*argv, "dstport") == 0) { | |
57 | NEXT_ARG(); | |
58 | check_duparg(&attrs, IFLA_BAREUDP_PORT, "dstport", | |
59 | *argv); | |
60 | if (get_be16(&dstport, *argv, 0)) | |
61 | invarg("dstport", *argv); | |
62 | } else if (matches(*argv, "ethertype") == 0) { | |
63 | NEXT_ARG(); | |
64 | check_duparg(&attrs, IFLA_BAREUDP_ETHERTYPE, | |
65 | "ethertype", *argv); | |
66 | if (ll_proto_a2n(ðertype, *argv)) | |
67 | invarg("ethertype", *argv); | |
68 | } else if (matches(*argv, "srcportmin") == 0) { | |
69 | NEXT_ARG(); | |
70 | check_duparg(&attrs, IFLA_BAREUDP_SRCPORT_MIN, | |
71 | "srcportmin", *argv); | |
72 | if (get_u16(&srcportmin, *argv, 0)) | |
73 | invarg("srcportmin", *argv); | |
74 | } else if (matches(*argv, "multiproto") == 0) { | |
75 | check_duparg(&attrs, IFLA_BAREUDP_MULTIPROTO_MODE, | |
76 | *argv, *argv); | |
77 | multiproto = true; | |
78 | } else if (matches(*argv, "nomultiproto") == 0) { | |
79 | check_duparg(&attrs, IFLA_BAREUDP_MULTIPROTO_MODE, | |
80 | *argv, *argv); | |
81 | multiproto = false; | |
82 | } else if (matches(*argv, "help") == 0) { | |
83 | explain(); | |
84 | return -1; | |
85 | } else { | |
86 | fprintf(stderr, "bareudp: unknown command \"%s\"?\n", | |
87 | *argv); | |
88 | explain(); | |
89 | return -1; | |
90 | } | |
91 | argc--, argv++; | |
92 | } | |
93 | ||
94 | if (!BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_PORT)) | |
95 | missarg("dstport"); | |
96 | if (!BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_ETHERTYPE)) | |
97 | missarg("ethertype"); | |
98 | ||
99 | addattr16(n, 1024, IFLA_BAREUDP_PORT, dstport); | |
100 | addattr16(n, 1024, IFLA_BAREUDP_ETHERTYPE, ethertype); | |
101 | if (BAREUDP_ATTRSET(attrs, IFLA_BAREUDP_SRCPORT_MIN)) | |
102 | addattr16(n, 1024, IFLA_BAREUDP_SRCPORT_MIN, srcportmin); | |
103 | if (multiproto) | |
104 | addattr(n, 1024, IFLA_BAREUDP_MULTIPROTO_MODE); | |
105 | ||
106 | return 0; | |
107 | } | |
108 | ||
109 | static void bareudp_print_opt(struct link_util *lu, FILE *f, | |
110 | struct rtattr *tb[]) | |
111 | { | |
112 | if (!tb) | |
113 | return; | |
114 | ||
115 | if (tb[IFLA_BAREUDP_PORT]) | |
116 | print_uint(PRINT_ANY, "dstport", "dstport %u ", | |
117 | rta_getattr_be16(tb[IFLA_BAREUDP_PORT])); | |
118 | ||
119 | if (tb[IFLA_BAREUDP_ETHERTYPE]) { | |
120 | struct rtattr *attr = tb[IFLA_BAREUDP_ETHERTYPE]; | |
121 | SPRINT_BUF(ethertype); | |
122 | ||
123 | print_string(PRINT_ANY, "ethertype", "ethertype %s ", | |
124 | ll_proto_n2a(rta_getattr_u16(attr), | |
125 | ethertype, sizeof(ethertype))); | |
126 | } | |
127 | ||
128 | if (tb[IFLA_BAREUDP_SRCPORT_MIN]) | |
129 | print_uint(PRINT_ANY, "srcportmin", "srcportmin %u ", | |
130 | rta_getattr_u16(tb[IFLA_BAREUDP_SRCPORT_MIN])); | |
131 | ||
132 | if (tb[IFLA_BAREUDP_MULTIPROTO_MODE]) | |
133 | print_bool(PRINT_ANY, "multiproto", "multiproto ", true); | |
134 | else | |
135 | print_bool(PRINT_ANY, "multiproto", "nomultiproto ", false); | |
136 | } | |
137 | ||
138 | static void bareudp_print_help(struct link_util *lu, int argc, char **argv, | |
139 | FILE *f) | |
140 | { | |
141 | print_explain(f); | |
142 | } | |
143 | ||
144 | struct link_util bareudp_link_util = { | |
145 | .id = "bareudp", | |
146 | .maxattr = IFLA_BAREUDP_MAX, | |
147 | .parse_opt = bareudp_parse_opt, | |
148 | .print_opt = bareudp_print_opt, | |
149 | .print_help = bareudp_print_help, | |
150 | }; |