• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * iplink_hsr.c	HSR device support
3  *
4  *		This program is free software; you can redistribute it and/or
5  *		modify it under the terms of the GNU General Public License
6  *		as published by the Free Software Foundation; either version
7  *		2 of the License, or (at your option) any later version.
8  *
9  * Authors:	Arvid Brodin <arvid.brodin@alten.se>
10  *
11  *		Based on iplink_vlan.c by Patrick McHardy <kaber@trash.net>
12  */
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <sys/socket.h>  /* Needed by linux/if.h for some reason */
18 #include <linux/if.h>
19 #include <linux/if_arp.h>
20 #include "rt_names.h"
21 #include "utils.h"
22 #include "ip_common.h"
23 
print_usage(FILE * f)24 static void print_usage(FILE *f)
25 {
26 	fprintf(f,
27 "Usage:\tip link add name NAME type hsr slave1 SLAVE1-IF slave2 SLAVE2-IF\n"
28 "\t[ supervision ADDR-BYTE ] [version VERSION]\n"
29 "\n"
30 "NAME\n"
31 "	name of new hsr device (e.g. hsr0)\n"
32 "SLAVE1-IF, SLAVE2-IF\n"
33 "	the two slave devices bound to the HSR device\n"
34 "ADDR-BYTE\n"
35 "	0-255; the last byte of the multicast address used for HSR supervision\n"
36 "	frames (default = 0)\n"
37 "VERSION\n"
38 "	0,1; the protocol version to be used. (default = 0)\n");
39 }
40 
usage(void)41 static void usage(void)
42 {
43 	print_usage(stderr);
44 }
45 
hsr_parse_opt(struct link_util * lu,int argc,char ** argv,struct nlmsghdr * n)46 static int hsr_parse_opt(struct link_util *lu, int argc, char **argv,
47 			 struct nlmsghdr *n)
48 {
49 	int ifindex;
50 	unsigned char multicast_spec;
51 	unsigned char protocol_version;
52 
53 	while (argc > 0) {
54 		if (matches(*argv, "supervision") == 0) {
55 			NEXT_ARG();
56 			if (get_u8(&multicast_spec, *argv, 0))
57 				invarg("ADDR-BYTE is invalid", *argv);
58 			addattr_l(n, 1024, IFLA_HSR_MULTICAST_SPEC,
59 				  &multicast_spec, 1);
60 		} else if (matches(*argv, "version") == 0) {
61 			NEXT_ARG();
62 			if (!(get_u8(&protocol_version, *argv, 0) == 0 ||
63 			      get_u8(&protocol_version, *argv, 0) == 1))
64 				invarg("version is invalid", *argv);
65 			addattr_l(n, 1024, IFLA_HSR_VERSION,
66 				  &protocol_version, 1);
67 		} else if (matches(*argv, "slave1") == 0) {
68 			NEXT_ARG();
69 			ifindex = ll_name_to_index(*argv);
70 			if (ifindex == 0)
71 				invarg("No such interface", *argv);
72 			addattr_l(n, 1024, IFLA_HSR_SLAVE1, &ifindex, 4);
73 		} else if (matches(*argv, "slave2") == 0) {
74 			NEXT_ARG();
75 			ifindex = ll_name_to_index(*argv);
76 			if (ifindex == 0)
77 				invarg("No such interface", *argv);
78 			addattr_l(n, 1024, IFLA_HSR_SLAVE2, &ifindex, 4);
79 		} else if (matches(*argv, "help") == 0) {
80 			usage();
81 			return -1;
82 		} else {
83 			fprintf(stderr, "hsr: what is \"%s\"?\n", *argv);
84 			usage();
85 			return -1;
86 		}
87 		argc--, argv++;
88 	}
89 
90 	return 0;
91 }
92 
hsr_print_opt(struct link_util * lu,FILE * f,struct rtattr * tb[])93 static void hsr_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
94 {
95 	SPRINT_BUF(b1);
96 
97 	if (!tb)
98 		return;
99 
100 	if (tb[IFLA_HSR_SLAVE1] &&
101 	    RTA_PAYLOAD(tb[IFLA_HSR_SLAVE1]) < sizeof(__u32))
102 		return;
103 	if (tb[IFLA_HSR_SLAVE2] &&
104 	    RTA_PAYLOAD(tb[IFLA_HSR_SLAVE2]) < sizeof(__u32))
105 		return;
106 	if (tb[IFLA_HSR_SEQ_NR] &&
107 	    RTA_PAYLOAD(tb[IFLA_HSR_SEQ_NR]) < sizeof(__u16))
108 		return;
109 	if (tb[IFLA_HSR_SUPERVISION_ADDR] &&
110 	    RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]) < ETH_ALEN)
111 		return;
112 
113 	if (tb[IFLA_HSR_SLAVE1])
114 		print_string(PRINT_ANY,
115 			     "slave1",
116 			     "slave1 %s ",
117 			     ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1])));
118 	else
119 		print_null(PRINT_ANY, "slave1", "slave1 %s ", "<none>");
120 
121 	if (tb[IFLA_HSR_SLAVE2])
122 		print_string(PRINT_ANY,
123 			     "slave2",
124 			     "slave2 %s ",
125 			     ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2])));
126 	else
127 		print_null(PRINT_ANY, "slave2", "slave2 %s ", "<none>");
128 
129 	if (tb[IFLA_HSR_SEQ_NR])
130 		print_int(PRINT_ANY,
131 			  "seq_nr",
132 			  "sequence %d ",
133 			  rta_getattr_u16(tb[IFLA_HSR_SEQ_NR]));
134 
135 	if (tb[IFLA_HSR_SUPERVISION_ADDR])
136 		print_string(PRINT_ANY,
137 			     "supervision_addr",
138 			     "supervision %s ",
139 			     ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]),
140 					 RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]),
141 					 ARPHRD_VOID,
142 					 b1, sizeof(b1)));
143 }
144 
hsr_print_help(struct link_util * lu,int argc,char ** argv,FILE * f)145 static void hsr_print_help(struct link_util *lu, int argc, char **argv,
146 	FILE *f)
147 {
148 	print_usage(f);
149 }
150 
151 struct link_util hsr_link_util = {
152 	.id		= "hsr",
153 	.maxattr	= IFLA_HSR_MAX,
154 	.parse_opt	= hsr_parse_opt,
155 	.print_opt	= hsr_print_opt,
156 	.print_help	= hsr_print_help,
157 };
158