]> git.saurik.com Git - apple/network_cmds.git/blob - ifconfig.tproj/ifbond.c
cb6d54223666f5b31c4cb194e04e5de4ac9b50a5
[apple/network_cmds.git] / ifconfig.tproj / ifbond.c
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * ifbond.c
26 * - add and remove interfaces from a bond interface
27 */
28
29 /*
30 * Modification History:
31 *
32 * July 14, 2004 Dieter Siegmund (dieter@apple.com)
33 * - created
34 */
35
36 #include <sys/param.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39
40 #include <stdlib.h>
41 #include <unistd.h>
42
43 #include <net/ethernet.h>
44 #include <net/if.h>
45 #include <net/if_var.h>
46 #include <net/if_bond_var.h>
47
48 #include <net/route.h>
49
50 #include <ctype.h>
51 #include <stdio.h>
52 #include <string.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <err.h>
56 #include <errno.h>
57
58 #include "ifconfig.h"
59 extern int bond_details;
60
61 #define EA_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x"
62 #define EA_CH(e, i) ((u_char)((u_char *)(e))[(i)])
63 #define EA_LIST(ea) EA_CH(ea,0),EA_CH(ea,1),EA_CH(ea,2),EA_CH(ea,3),EA_CH(ea,4),EA_CH(ea,5)
64
65 static __inline__ const char *
66 selected_state_string(u_char s)
67 {
68 static const char * names[] = { "unselected", "selected", "standby" };
69
70 if (s <= IF_BOND_STATUS_SELECTED_STATE_STANDBY) {
71 return (names[s]);
72 }
73 return ("<unknown>");
74 }
75
76 static void
77 bond_print_details(struct if_bond_status * ibs_p, int count)
78
79 {
80 int i;
81 struct if_bond_status * scan_p = ibs_p;
82
83 for (i = 0; i < count; i++, scan_p++) {
84 struct if_bond_partner_state * ps;
85 ps = &scan_p->ibs_partner_state;
86 printf("\tbond interface: %s priority: 0x%04x "
87 "state: 0x%02x partner system: 0x%04x,"
88 EA_FORMAT " "
89 "key: 0x%04x port: 0x%04x priority: 0x%04x "
90 "state: 0x%02x\n",
91 scan_p->ibs_if_name, scan_p->ibs_port_priority,
92 scan_p->ibs_state, ps->ibps_system_priority,
93 EA_LIST(&ps->ibps_system), ps->ibps_key,
94 ps->ibps_port, ps->ibps_port_priority,
95 ps->ibps_state);
96 }
97 return;
98 }
99
100 void
101 bond_status(int s, struct rt_addrinfo * info __unused)
102 {
103 int i;
104 struct if_bond_req ibr;
105 struct if_bond_status * ibs_p;
106 struct if_bond_status_req * ibsr_p;
107
108 bzero((char *)&ibr, sizeof(ibr));
109 ibr.ibr_op = IF_BOND_OP_GET_STATUS;
110 ibsr_p = &ibr.ibr_ibru.ibru_status;
111 ibsr_p->ibsr_version = IF_BOND_STATUS_REQ_VERSION;
112 ifr.ifr_data = (caddr_t)&ibr;
113
114 /* how many of them are there? */
115 if (ioctl(s, SIOCGIFBOND, (caddr_t)&ifr) < 0) {
116 return;
117 }
118 if (ibsr_p->ibsr_total == 0) {
119 if (bond_details) {
120 printf("\tbond key: 0x%04x interfaces: <none>\n",
121 ibsr_p->ibsr_key);
122 }
123 else {
124 printf("\tbond interfaces: <none>\n");
125 }
126 return;
127 }
128 ibsr_p->ibsr_buffer
129 = (char *)malloc(sizeof(struct if_bond_status)
130 * ibsr_p->ibsr_total);
131 ibsr_p->ibsr_count = ibsr_p->ibsr_total;
132
133 /* get the list */
134 if (ioctl(s, SIOCGIFBOND, (caddr_t)&ifr) < 0) {
135 goto done;
136 }
137 if (ibsr_p->ibsr_total > 0) {
138 if (bond_details) {
139 printf("\tbond key: 0x%04x interfaces:",
140 ibsr_p->ibsr_key);
141 }
142 else {
143 printf("\tbond interfaces:");
144 }
145 ibs_p = (struct if_bond_status *)ibsr_p->ibsr_buffer;
146 for (i = 0; i < ibsr_p->ibsr_total; i++, ibs_p++) {
147 printf(" %s", ibs_p->ibs_if_name);
148 if (bond_details) {
149 u_char s = ibs_p->ibs_selected_state;
150 printf(" (%s)", selected_state_string(s));
151 }
152 }
153 printf("\n");
154 if (bond_details) {
155 bond_print_details((struct if_bond_status *)
156 ibsr_p->ibsr_buffer,
157 ibsr_p->ibsr_total);
158 }
159 }
160 else if (bond_details) {
161 printf("\tbond key: 0x%04x interfaces: <none>\n",
162 ibsr_p->ibsr_key);
163 }
164 else {
165 printf("\tbond interfaces: <none>\n");
166 }
167
168 done:
169 free(ibsr_p->ibsr_buffer);
170 return;
171 }
172
173 void
174 setbonddev(const char *val, int d, int s, const struct afswtch * afp)
175 {
176 struct if_bond_req ibr;
177
178 bzero((char *)&ibr, sizeof(ibr));
179 if ((unsigned int)snprintf(ibr.ibr_ibru.ibru_if_name,
180 sizeof(ibr.ibr_ibru.ibru_if_name),
181 "%s", val) >= IFNAMSIZ) {
182 errx(1, "interface name too long");
183 }
184 ibr.ibr_op = IF_BOND_OP_ADD_INTERFACE;
185 ifr.ifr_data = (caddr_t)&ibr;
186 if (ioctl(s, SIOCSIFBOND, (caddr_t)&ifr) == -1)
187 err(1, "SIOCSIFBOND add interface");
188
189 return;
190 }
191
192 void
193 unsetbonddev(const char *val, int d, int s, const struct afswtch * afp)
194 {
195 struct if_bond_req ibr;
196
197 bzero((char *)&ibr, sizeof(ibr));
198 if ((unsigned int)snprintf(ibr.ibr_ibru.ibru_if_name,
199 sizeof(ibr.ibr_ibru.ibru_if_name),
200 "%s", val) >= IFNAMSIZ) {
201 errx(1, "interface name too long");
202 }
203 ibr.ibr_op = IF_BOND_OP_REMOVE_INTERFACE;
204 ifr.ifr_data = (caddr_t)&ibr;
205 if (ioctl(s, SIOCSIFBOND, (caddr_t)&ifr) == -1)
206 err(1, "SIOCSIFBOND remove interface");
207
208 return;
209 }
210