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