make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / Documentation / networking / ifenslave.c
1 /* Mode: C;
2  * ifenslave.c: Configure network interfaces for parallel routing.
3  *
4  *      This program controls the Linux implementation of running multiple
5  *      network interfaces in parallel.
6  *
7  * Usage:       ifenslave [-v] master-interface < slave-interface [metric <N>] > ...
8  *
9  * Author:      Donald Becker <becker@cesdis.gsfc.nasa.gov>
10  *              Copyright 1994-1996 Donald Becker
11  *
12  *              This program is free software; you can redistribute it
13  *              and/or modify it under the terms of the GNU General Public
14  *              License as published by the Free Software Foundation.
15  *
16  *      The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
17  *      Center of Excellence in Space Data and Information Sciences
18  *         Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
19  *
20  *  Changes :
21  *    - 2000/10/02 Willy Tarreau <willy at meta-x.org> :
22  *       - few fixes. Master's MAC address is now correctly taken from
23  *         the first device when not previously set ;
24  *       - detach support : call BOND_RELEASE to detach an enslaved interface.
25  *       - give a mini-howto from command-line help : # ifenslave -h
26  *
27  *    - 2001/02/16 Chad N. Tindel <ctindel at ieee dot org> :
28  *       - Master is now brought down before setting the MAC address.  In
29  *         the 2.4 kernel you can't change the MAC address while the device is
30  *         up because you get EBUSY.  
31  *
32  *    - 2001/09/13 Takao Indoh <indou dot takao at jp dot fujitsu dot com>
33  *       - Added the ability to change the active interface on a mode 1 bond
34  *         at runtime.
35  *
36  *    - 2001/10/23 Chad N. Tindel <ctindel at ieee dot org> :
37  *       - No longer set the MAC address of the master.  The bond device will
38  *         take care of this itself
39  *       - Try the SIOC*** versions of the bonding ioctls before using the
40  *         old versions
41  *    - 2002/02/18 Erik Habbinga <erik_habbinga @ hp dot com> :
42  *       - ifr2.ifr_flags was not initialized in the hwaddr_notset case,
43  *         SIOCGIFFLAGS now called before hwaddr_notset test
44  *
45  *    - 2002/10/31 Tony Cureington <tony.cureington * hp_com> :
46  *       - If the master does not have a hardware address when the first slave
47  *         is enslaved, the master is assigned the hardware address of that 
48  *         slave - there is a comment in bonding.c stating "ifenslave takes 
49  *         care of this now." This corrects the problem of slaves having 
50  *         different hardware addresses in active-backup mode when 
51  *         multiple interfaces are specified on a single ifenslave command
52  *         (ifenslave bond0 eth0 eth1).
53  *
54  */
55
56 static char *version =
57 "ifenslave.c:v0.07 9/9/97  Donald Becker (becker@cesdis.gsfc.nasa.gov).\n"
58 "detach support added on 2000/10/02 by Willy Tarreau (willy at meta-x.org).\n"
59 "2.4 kernel support added on 2001/02/16 by Chad N. Tindel (ctindel at ieee dot org.\n";
60
61 static const char *usage_msg =
62 "Usage: ifenslave [-adfrvVh] <master-interface> < <slave-if> [metric <N>] > ...\n"
63 "       ifenslave -c master-interface slave-if\n";
64
65 static const char *howto_msg =
66 "Usage: ifenslave [-adfrvVh] <master-interface> < <slave-if> [metric <N>] > ...\n"
67 "       ifenslave -c master-interface slave-if\n"
68 "\n"
69 "       To create a bond device, simply follow these three steps :\n"
70 "       - ensure that the required drivers are properly loaded :\n"
71 "         # modprobe bonding ; modprobe <3c59x|eepro100|pcnet32|tulip|...>\n"
72 "       - assign an IP address to the bond device :\n"
73 "         # ifconfig bond0 <addr> netmask <mask> broadcast <bcast>\n"
74 "       - attach all the interfaces you need to the bond device :\n"
75 "         # ifenslave bond0 eth0 eth1 eth2\n"
76 "         If bond0 didn't have a MAC address, it will take eth0's. Then, all\n"
77 "         interfaces attached AFTER this assignment will get the same MAC addr.\n"
78 "\n"
79 "       To detach a dead interface without setting the bond device down :\n"
80 "         # ifenslave -d bond0 eth1\n"
81 "\n"
82 "       To set the bond device down and automatically release all the slaves :\n"
83 "         # ifconfig bond0 down\n"
84 "\n"
85 "       To change active slave :\n"
86 "         # ifenslave -c bond0 eth0\n"
87 "\n";
88
89 #include <unistd.h>
90 #include <stdlib.h>
91 #include <stdio.h>
92 #include <ctype.h>
93 #include <string.h>
94 #include <errno.h>
95 #include <fcntl.h>
96 #include <getopt.h>
97 #include <sys/types.h>
98 #include <sys/socket.h>
99 #include <sys/ioctl.h>
100 #include <linux/if.h>
101 #include <linux/if_arp.h>
102 #include <linux/if_ether.h>
103 #include <linux/if_bonding.h>
104 #include <linux/sockios.h>
105
106 struct option longopts[] = {
107  /* { name  has_arg  *flag  val } */
108     {"all-interfaces", 0, 0, 'a'},      /* Show all interfaces. */
109     {"force",       0, 0, 'f'},         /* Force the operation. */
110     {"help",            0, 0, '?'},             /* Give help */
111         {"howto",       0, 0, 'h'},     /* Give some more help */
112     {"receive-slave", 0, 0, 'r'},       /* Make a receive-only slave.  */
113     {"verbose",         0, 0, 'v'},             /* Report each action taken.  */
114     {"version",         0, 0, 'V'},             /* Emit version information.  */
115     {"detach",       0, 0, 'd'},        /* Detach a slave interface. */
116     {"change-active", 0, 0, 'c'},       /* Change the active slave.  */
117     { 0, 0, 0, 0 }
118 };
119
120 /* Command-line flags. */
121 unsigned int
122 opt_a = 0,                                      /* Show-all-interfaces flag. */
123 opt_f = 0,                                      /* Force the operation. */
124 opt_r = 0,                                      /* Set up a Rx-only slave. */
125 opt_d = 0,                                      /* detach a slave interface. */
126 opt_c = 0,                                      /* change-active-slave flag. */
127 verbose = 0,                                    /* Verbose flag. */
128 opt_version = 0,
129 opt_howto = 0;
130 int skfd = -1;                                  /* AF_INET socket for ioctl() calls.    */
131
132 static void if_print(char *ifname);
133
134 int
135 main(int argc, char **argv)
136 {
137         struct ifreq  ifr2, if_hwaddr, if_ipaddr, if_metric, if_mtu, if_dstaddr;
138         struct ifreq  if_netmask, if_brdaddr, if_flags;
139         int goterr = 0;
140         int c, errflag = 0;
141         sa_family_t master_family;
142         char **spp, *master_ifname, *slave_ifname;
143         int hwaddr_notset;
144         int master_up;
145
146         while ((c = getopt_long(argc, argv, "acdfrvV?h", longopts, 0)) != EOF)
147                 switch (c) {
148                 case 'a': opt_a++; break;
149                 case 'f': opt_f++; break;
150                 case 'r': opt_r++; break;
151                 case 'd': opt_d++; break;
152                 case 'c': opt_c++; break;
153                 case 'v': verbose++;            break;
154                 case 'V': opt_version++;        break;
155                 case 'h': opt_howto++;  break;
156                 case '?': errflag++;
157                 }
158
159         /* option check */
160         if (opt_c)
161                 if(opt_a || opt_f || opt_r || opt_d || verbose || opt_version ||
162                    opt_howto || errflag ) {
163                         fprintf(stderr, usage_msg);
164                         return 2;
165                 }
166
167         if (errflag) {
168                 fprintf(stderr, usage_msg);
169                 return 2;
170         }
171
172         if (opt_howto) {
173                 fprintf(stderr, howto_msg);
174                 return 0;
175         }
176
177         if (verbose || opt_version) {
178                 printf(version);
179                 if (opt_version)
180                         exit(0);
181         }
182
183         /* Open a basic socket. */
184         if ((skfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
185                 perror("socket");
186                 exit(-1);
187         }
188
189         if (verbose)
190                 fprintf(stderr, "DEBUG: argc=%d, optind=%d and argv[optind] is %s.\n",
191                                 argc, optind, argv[optind]);
192
193         /* No remaining args means show all interfaces. */
194         if (optind == argc) {
195                 if_print((char *)NULL);
196                 (void) close(skfd);
197                 exit(0);
198         }
199
200         /* Copy the interface name. */
201         spp = argv + optind;
202         master_ifname = *spp++;
203         slave_ifname = *spp++;
204
205         /* Check command line. */
206         if (opt_c) {
207                 char **tempp = spp;
208                 if ((master_ifname == NULL)||(slave_ifname == NULL)||(*tempp++ != NULL)) {
209                         fprintf(stderr, usage_msg);
210                         return 2;
211                 }
212         }
213
214         /* A single args means show the configuration for this interface. */
215         if (slave_ifname == NULL) {
216                 if_print(master_ifname);
217                 (void) close(skfd);
218                 exit(0);
219         }
220
221         /* Get the vitals from the master interface. */
222         {
223                 struct ifreq *ifra[7] = { &if_ipaddr, &if_mtu, &if_dstaddr,
224                                                                   &if_brdaddr, &if_netmask, &if_flags,
225                                                                   &if_hwaddr };
226                 const char *req_name[7] = {
227                         "IP address", "MTU", "destination address",
228                         "broadcast address", "netmask", "status flags",
229                         "hardware address" };
230                 const int ioctl_req_type[7] = {
231                         SIOCGIFADDR, SIOCGIFMTU, SIOCGIFDSTADDR,
232                         SIOCGIFBRDADDR, SIOCGIFNETMASK, SIOCGIFFLAGS,
233                         SIOCGIFHWADDR };
234                 int i;
235
236                 for (i = 0; i < 7; i++) {
237                         strncpy(ifra[i]->ifr_name, master_ifname, IFNAMSIZ);
238                         if (ioctl(skfd, ioctl_req_type[i], ifra[i]) < 0) {
239                                 fprintf(stderr,
240                                                 "Something broke getting the master's %s: %s.\n",
241                                                 req_name[i], strerror(errno));
242                         }
243                 }
244
245                 hwaddr_notset = 1; /* assume master's address not set yet */
246                 for (i = 0; hwaddr_notset && (i < 6); i++) {
247                         hwaddr_notset &= ((unsigned char *)if_hwaddr.ifr_hwaddr.sa_data)[i] == 0;
248                 }
249
250                 /* The family '1' is ARPHRD_ETHER for ethernet. */
251                 if (if_hwaddr.ifr_hwaddr.sa_family != 1 && !opt_f) {
252                         fprintf(stderr, "The specified master interface '%s' is not"
253                                         " ethernet-like.\n  This program is designed to work"
254                                         " with ethernet-like network interfaces.\n"
255                                         " Use the '-f' option to force the operation.\n",
256                                         master_ifname);
257
258                         exit (1);
259                 }
260                 master_family = if_hwaddr.ifr_hwaddr.sa_family;
261                 if (verbose) {
262                         unsigned char *hwaddr = (unsigned char *)if_hwaddr.ifr_hwaddr.sa_data;
263                         printf("The current hardware address (SIOCGIFHWADDR) of %s is type %d  "
264                                    "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", master_ifname,
265                                    if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
266                                    hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
267                 }
268         }
269
270
271         /* do this when enslaving interfaces */
272         do {
273                 if (opt_d) {  /* detach a slave interface from the master */
274                         strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
275                         strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
276                         if ((ioctl(skfd, SIOCBONDRELEASE, &if_flags) < 0) &&
277                                 (ioctl(skfd, BOND_RELEASE_OLD, &if_flags) < 0)) {
278                                         fprintf(stderr, "SIOCBONDRELEASE: cannot detach %s from %s. errno=%s.\n",
279                                                         slave_ifname, master_ifname, strerror(errno));
280                         }
281                         else {  /* we'll set the interface down to avoid any conflicts due to
282                                            same IP/MAC */
283                                 strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
284                                 if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
285                                         int saved_errno = errno;
286                                         fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
287                                                         strerror(saved_errno));
288                                 }
289                                 else {
290                                         ifr2.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
291                                         if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
292                                                 int saved_errno = errno;
293                                                 fprintf(stderr, "Shutting down interface %s failed: %s\n",
294                                                                 slave_ifname, strerror(saved_errno));
295                                         }
296                                 }
297                         }
298                 }
299                 else {  /* attach a slave interface to the master */
300                         /* two possibilities :
301                            - if hwaddr_notset, do nothing.  The bond will assign the
302                              hwaddr from it's first slave.
303                            - if !hwaddr_notset, assign the master's hwaddr to each slave
304                         */
305
306                         strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
307                         if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
308                                 int saved_errno = errno;
309                                 fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
310                                                 strerror(saved_errno));
311                                 return 1;
312                         }
313
314                         if (hwaddr_notset) {
315                                 /* assign the slave hw address to the 
316                                  * master since it currently does not 
317                                  * have one; otherwise, slaves may
318                                  * have different hw addresses in 
319                                  * active-backup mode as seen when enslaving 
320                                  * using "ifenslave bond0 eth0 eth1" because
321                                  * hwaddr_notset is set outside this loop.
322                                  * TODO: put this and the "else" portion in
323                                  *       a function.
324                                  */
325                                 goterr = 0;
326                                 master_up = 0;
327                                 if (if_flags.ifr_flags & IFF_UP) {
328                                         if_flags.ifr_flags &= ~IFF_UP;
329                                         if (ioctl(skfd, SIOCSIFFLAGS, 
330                                                         &if_flags) < 0) {
331                                                 goterr = 1;
332                                                 fprintf(stderr, 
333                                                         "Shutting down "
334                                                         "interface %s failed: "
335                                                         "%s\n",
336                                                         master_ifname, 
337                                                         strerror(errno));
338                                         } else {
339                                                 /* we took the master down, 
340                                                  * so we must bring it up 
341                                                  */
342                                                 master_up = 1; 
343                                         }
344                                 }
345
346                                 if (!goterr) {
347                                         /* get the slaves MAC address */
348                                         strncpy(if_hwaddr.ifr_name, 
349                                                         slave_ifname, IFNAMSIZ);
350                                         if (ioctl(skfd, SIOCGIFHWADDR, 
351                                                         &if_hwaddr) < 0) {
352                                                 fprintf(stderr, 
353                                                         "Could not get MAC "
354                                                         "address of %s: %s\n",
355                                                         slave_ifname, 
356                                                         strerror(errno));
357                                                 strncpy(if_hwaddr.ifr_name, 
358                                                         master_ifname, 
359                                                         IFNAMSIZ);
360                                                 goterr=1;
361                                         }
362                                 }
363
364                                 if (!goterr) {
365                                         strncpy(if_hwaddr.ifr_name, 
366                                                 master_ifname, IFNAMSIZ);
367                                         if (ioctl(skfd, SIOCSIFHWADDR, 
368                                                         &if_hwaddr) < 0) {
369                                                 fprintf(stderr, 
370                                                         "Could not set MAC "
371                                                         "address of %s: %s\n",
372                                                         master_ifname, 
373                                                         strerror(errno));
374                                                 goterr=1;
375                                         } else {
376                                                 hwaddr_notset = 0;
377                                         }
378                                 }
379
380                                 if (master_up) {
381                                         if_flags.ifr_flags |= IFF_UP;
382                                         if (ioctl(skfd, SIOCSIFFLAGS, 
383                                                         &if_flags) < 0) {
384                                                 fprintf(stderr, 
385                                                         "Bringing up interface "
386                                                         "%s failed: %s\n",
387                                                         master_ifname, 
388                                                         strerror(errno));
389                                         }
390                                 }
391
392                         } else {  
393                                 /* we'll assign master's hwaddr to this slave */
394                                 if (ifr2.ifr_flags & IFF_UP) {
395                                         ifr2.ifr_flags &= ~IFF_UP;
396                                         if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
397                                                 int saved_errno = errno;
398                                                 fprintf(stderr, "Shutting down interface %s failed: %s\n",
399                                                                 slave_ifname, strerror(saved_errno));
400                                         }
401                                 }
402         
403                                 strncpy(if_hwaddr.ifr_name, slave_ifname, IFNAMSIZ);
404                                 if (ioctl(skfd, SIOCSIFHWADDR, &if_hwaddr) < 0) {
405                                         int saved_errno = errno;
406                                         fprintf(stderr, "SIOCSIFHWADDR on %s failed: %s\n", if_hwaddr.ifr_name,
407                                                         strerror(saved_errno));
408                                         if (saved_errno == EBUSY)
409                                                 fprintf(stderr, "  The slave device %s is busy: it must be"
410                                                                 " idle before running this command.\n", slave_ifname);
411                                         else if (saved_errno == EOPNOTSUPP)
412                                                 fprintf(stderr, "  The slave device you specified does not support"
413                                                                 " setting the MAC address.\n  Your kernel likely does not"
414                                                                 " support slave devices.\n");
415                                         else if (saved_errno == EINVAL)
416                                                 fprintf(stderr, "  The slave device's address type does not match"
417                                                                 " the master's address type.\n");
418                                 } else {
419                                         if (verbose) {
420                                                 unsigned char *hwaddr = if_hwaddr.ifr_hwaddr.sa_data;
421                                                 printf("Slave's (%s) hardware address set to "
422                                                            "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", slave_ifname,
423                                                            hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
424                                         }
425                                 }
426                         }
427         
428                         if (*spp  &&  !strcmp(*spp, "metric")) {
429                                 if (*++spp == NULL) {
430                                         fprintf(stderr, usage_msg);
431                                         exit(2);
432                                 }
433                                 if_metric.ifr_metric = atoi(*spp);
434                                 strncpy(if_metric.ifr_name, slave_ifname, IFNAMSIZ);
435                                 if (ioctl(skfd, SIOCSIFMETRIC, &if_metric) < 0) {
436                                         fprintf(stderr, "SIOCSIFMETRIC on %s: %s\n", slave_ifname,
437                                                         strerror(errno));
438                                         goterr = 1;
439                                 }
440                                 spp++;
441                         }
442         
443                         if (strncpy(if_ipaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
444                                 || ioctl(skfd, SIOCSIFADDR, &if_ipaddr) < 0) {
445                                 fprintf(stderr,
446                                                 "Something broke setting the slave's address: %s.\n",
447                                                 strerror(errno));
448                         } else {
449                                 if (verbose) {
450                                         unsigned char *ipaddr = if_ipaddr.ifr_addr.sa_data;
451                                         printf("Set the slave's (%s) IP address to %d.%d.%d.%d.\n",
452                                                    slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
453                                 }
454                         }
455         
456                         if (strncpy(if_mtu.ifr_name, slave_ifname, IFNAMSIZ) <= 0
457                                 || ioctl(skfd, SIOCSIFMTU, &if_mtu) < 0) { 
458                                 fprintf(stderr, "Something broke setting the slave MTU: %s.\n",
459                                                 strerror(errno));
460                         } else {
461                                 if (verbose)
462                                         printf("Set the slave's (%s) MTU to %d.\n", slave_ifname, if_mtu.ifr_mtu);
463                         }
464         
465                         if (strncpy(if_dstaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
466                                 || ioctl(skfd, SIOCSIFDSTADDR, &if_dstaddr) < 0) {
467                                 fprintf(stderr, "Error setting the slave (%s) with SIOCSIFDSTADDR: %s.\n",
468                                                 slave_ifname, strerror(errno));
469                         } else {
470                                 if (verbose) {
471                                         unsigned char *ipaddr = if_dstaddr.ifr_dstaddr.sa_data;
472                                         printf("Set the slave's (%s) destination address to %d.%d.%d.%d.\n",
473                                                    slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
474                                 }
475                         }
476         
477                         if (strncpy(if_brdaddr.ifr_name, slave_ifname, IFNAMSIZ) <= 0
478                                 || ioctl(skfd, SIOCSIFBRDADDR, &if_brdaddr) < 0) {
479                                 fprintf(stderr,
480                                                 "Something broke setting the slave (%s) broadcast address: %s.\n",
481                                                 slave_ifname, strerror(errno));
482                         } else {
483                                 if (verbose) {
484                                         unsigned char *ipaddr = if_brdaddr.ifr_broadaddr.sa_data;
485                                         printf("Set the slave's (%s) broadcast address to %d.%d.%d.%d.\n",
486                                                    slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
487                                 }
488                         }
489                         
490                         if (strncpy(if_netmask.ifr_name, slave_ifname, IFNAMSIZ) <= 0
491                                 || ioctl(skfd, SIOCSIFNETMASK, &if_netmask) < 0) {
492                                 fprintf(stderr,
493                                                 "Something broke setting the slave (%s) netmask: %s.\n",
494                                                 slave_ifname, strerror(errno));
495                         } else {
496                                 if (verbose) {
497                                         unsigned char *ipaddr = if_netmask.ifr_netmask.sa_data;
498                                         printf("Set the slave's (%s) netmask to %d.%d.%d.%d.\n",
499                                                    slave_ifname, ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
500                                 }
501                         }
502                         
503                         ifr2.ifr_flags |= IFF_UP; /* the interface will need to be up to be bonded */
504                         if ((ifr2.ifr_flags &= ~(IFF_SLAVE | IFF_MASTER)) == 0
505                                 || strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ) <= 0
506                                 || ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
507                                 fprintf(stderr,
508                                                 "Something broke setting the slave (%s) flags: %s.\n",
509                                                 slave_ifname, strerror(errno));
510                         } else {
511                                 if (verbose)
512                                         printf("Set the slave's (%s) flags %4.4x.\n", slave_ifname, if_flags.ifr_flags);
513                         }
514         
515                         /* Do the real thing */
516                         if ( ! opt_r) {
517                                 strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
518                                 strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
519                                 if (!opt_c) {
520                                         if ((ioctl(skfd, SIOCBONDENSLAVE, &if_flags) < 0) &&
521                                             (ioctl(skfd, BOND_ENSLAVE_OLD, &if_flags) < 0)) {
522                                                 fprintf(stderr, "SIOCBONDENSLAVE: %s.\n", strerror(errno));
523                                         }
524                                 }
525                                 else {
526                                         if ((ioctl(skfd, SIOCBONDCHANGEACTIVE, &if_flags) < 0) &&
527                                             (ioctl(skfd, BOND_CHANGE_ACTIVE_OLD, &if_flags) < 0)) {
528                                                 fprintf(stderr, "SIOCBONDCHANGEACTIVE: %s.\n", strerror(errno));
529                                         }
530                                 }
531                         }
532                 }
533         } while ( (slave_ifname = *spp++) != NULL);
534
535         /* Close the socket. */
536         (void) close(skfd);
537
538         return(goterr);
539 }
540
541 static short mif_flags;
542
543 /* Get the inteface configuration from the kernel. */
544 static int if_getconfig(char *ifname)
545 {
546         struct ifreq ifr;
547         int metric, mtu;                        /* Parameters of the master interface. */
548         struct sockaddr dstaddr, broadaddr, netmask;
549
550         strcpy(ifr.ifr_name, ifname);
551         if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
552                 return -1;
553         mif_flags = ifr.ifr_flags;
554         printf("The result of SIOCGIFFLAGS on %s is %x.\n",
555                    ifname, ifr.ifr_flags);
556
557         strcpy(ifr.ifr_name, ifname);
558         if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
559                 return -1;
560         printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",
561                    ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
562                    ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);
563
564         strcpy(ifr.ifr_name, ifname);
565         if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
566                 return -1;
567
568         {
569                 /* Gotta convert from 'char' to unsigned for printf().  */
570                 unsigned char *hwaddr = (unsigned char *)ifr.ifr_hwaddr.sa_data;
571                 printf("The result of SIOCGIFHWADDR is type %d  "
572                            "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
573                            ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
574                            hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
575         }
576
577         strcpy(ifr.ifr_name, ifname);
578         if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
579                 metric = 0;
580         } else
581                 metric = ifr.ifr_metric;
582
583         strcpy(ifr.ifr_name, ifname);
584         if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
585                 mtu = 0;
586         else
587                 mtu = ifr.ifr_mtu;
588
589         strcpy(ifr.ifr_name, ifname);
590         if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) {
591                 memset(&dstaddr, 0, sizeof(struct sockaddr));
592         } else
593                 dstaddr = ifr.ifr_dstaddr;
594
595         strcpy(ifr.ifr_name, ifname);
596         if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) {
597                 memset(&broadaddr, 0, sizeof(struct sockaddr));
598         } else
599                 broadaddr = ifr.ifr_broadaddr;
600
601         strcpy(ifr.ifr_name, ifname);
602         if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) {
603                 memset(&netmask, 0, sizeof(struct sockaddr));
604         } else
605                 netmask = ifr.ifr_netmask;
606
607         return(0);
608 }
609
610 static void if_print(char *ifname)
611 {
612         char buff[1024];
613         struct ifconf ifc;
614         struct ifreq *ifr;
615         int i;
616
617         if (ifname == (char *)NULL) {
618                 ifc.ifc_len = sizeof(buff);
619                 ifc.ifc_buf = buff;
620                 if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
621                         fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
622                         return;
623                 }
624
625                 ifr = ifc.ifc_req;
626                 for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
627                         if (if_getconfig(ifr->ifr_name) < 0) {
628                                 fprintf(stderr, "%s: unknown interface.\n",
629                                                 ifr->ifr_name);
630                                 continue;
631                         }
632
633                         if (((mif_flags & IFF_UP) == 0) && !opt_a) continue;
634                         /*ife_print(&ife);*/
635                 }
636         } else {
637                 if (if_getconfig(ifname) < 0)
638                         fprintf(stderr, "%s: unknown interface.\n", ifname);
639         }
640 }
641
642 \f
643 /*
644  * Local variables:
645  *  version-control: t
646  *  kept-new-versions: 5
647  *  c-indent-level: 4
648  *  c-basic-offset: 4
649  *  tab-width: 4
650  *  compile-command: "gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave"
651  * End:
652  */