Git init
[external/ifupdown.git] / ifupdown.nw
1 %
2 \documentclass{article}
3 \usepackage{graphicx}
4 \usepackage{noweb}
5 \pagestyle{noweb}
6 \noweboptions{smallcode,hideunuseddefs}
7 \begin{document}
8 @
9
10 \def\nwendcode{\endtrivlist\endgroup}
11 \let\nwdocspar=\relax
12
13 \title{ Interface Tools\thanks{
14 Copyright \copyright\ 1999--2005 Anthony Towns. This program is free
15 software; you can redistribute it and/or modify it under the terms of
16 the GNU General Public License as published by the Free Software
17 Foundation; either version 2 of the License, or (at your option) any
18 later version.  
19 }}
20
21 \author{ Anthony Towns \\ { \tt aj@azure.humbug.org.au } }
22
23 \pagenumbering{roman}
24
25 \maketitle
26 \tableofcontents
27
28 \vfill
29 \pagebreak
30 \pagenumbering{arabic}
31
32 \section{Introduction}
33
34 This source defines the commands [[ifup]] and [[ifdown]], used to
35 manipulate interfaces in an easily controllable manner.
36
37 \subsection{Assumed Knowledge}
38
39 The reader is assumed to have knowledge of the C \cite{K&R} and Perl
40 \cite{camel} programming languages in a Unix environment \cite{StevensUnix}.
41 A cursory understanding of network administration on the appropriate
42 platform is also assumed, along with access to the relevant manual
43 pages as necessary.
44
45 This source has been written as a literate program using the [[noweb]]
46 \cite{wwwnoweb} tool suite, and typeset using \LaTeX\ \cite{latex}.
47
48 \subsection{Program Structure}
49
50 We shall decompose this program into four main areas of functionality:
51 compile-time configuration, run-time configuration, execution, and the
52 overall driver.
53
54 Compile-time configuration will deal with differing available address
55 families (IP vs IPX vs IPv6, and so on), and the differing methods of
56 enabling and disabling interfaces configured for each family. This will
57 be implemented using the [[addrfam]] module, and various [[.defn]] files,
58 for the address family definitions.
59
60 Run-time configuration will deal with determining the local setup
61 based on the file [[/etc/network/interfaces]], and producing a data
62 structure encapsulating these details. This will be implemented in the
63 [[config]] module.
64
65 Execution will deal with issues relating to working out exactly which
66 commands to run based on a somewhat abstract description from the
67 compile-time configuration and the details determined at
68 run-time. This will be dealt with in the [[execute]] module.
69
70 The remaining work --- argument parsing, error reporting, and,
71 essentially, putting all the pieces together --- is done by the
72 [[main]] module.
73
74 The following diagram gives a brief idea of the information and control
75 flow amongst the modules.
76
77 \begin{center}
78 \includegraphics[height=45mm]{modules}
79 \end{center}
80
81 Much of the information sharing will be done by defining and filling
82 in some data structures and allowing the other modules to just access
83 that information directly. Rather than hiding the information itself,
84 most of our modules simply attempt to hide how that information was
85 originally written. Because of this, we shall find that these modules are
86 too closely linked to be completely separated in a convenient manner,
87 so they will all make use of a single header file for each other's
88 structure definitions, exported interfaces and so on.
89
90 <<header.h>>=
91 #ifndef HEADER_H
92 #define HEADER_H
93
94 <<type definitions>>
95 <<function type definitions>>
96 <<structure definitions>>
97 <<constant definitions>>
98 <<exported symbols>>
99
100 #endif /* HEADER_H */
101
102
103 \section{The Build System}
104
105 We shall begin with the template for the Makefile we shall use.
106
107 <<Makefile>>=
108 <<make options>>
109
110 CFILES := addrfam.c execute.c config.c main.c archlinux.c
111 HFILES := header.h archlinux.h
112 PERLFILES := defn2c.pl defn2man.pl
113 DEFNFILES := inet.defn ipx.defn inet6.defn
114
115 OBJ := main.o addrfam.o execute.o config.o \
116         $(patsubst %.defn,%.o,$(DEFNFILES)) archlinux.o
117
118 MAN := $(patsubst %.defn,%.man,$(DEFNFILES))
119
120 default : executables
121 all : executables docs
122
123 executables : ifup ifdown ifup.8 ifdown.8 interfaces.5
124 docs : ifupdown.ps.gz ifup.8.ps.gz interfaces.5.ps.gz ifupdown.pdf
125
126 .PHONY : executables 
127 <<phony targets>>
128 <<executable targets>>
129 <<manpage targets>>
130 <<extra dependencies>>
131 <<implicit rules>>
132
133 <<generated dependency inclusion>>
134
135
136 We shall build exactly two executables, [[ifup]] and [[ifdown]], which
137 will in truth simply be two names for a single binary, albeit with
138 different functionality.
139
140 <<executable targets>>=
141 ifup: $(OBJ)
142         $(CC) $(CFLAGS) $^ $(LDFLAGS) $(OUTPUT_OPTION)
143
144 ifdown: ifup
145         ln -sf ifup ifdown
146
147
148 Both of these executables have a manpage. Since they're actually the
149 same executable, what could be more appropriate than them having the
150 same manpage too?
151
152 <<manpage targets>>=
153 interfaces.5: interfaces.5.pre $(MAN)
154         sed $(foreach man,$(MAN),-e '/^##ADDRESSFAM##$$/r $(man)') \
155              -e '/^##ADDRESSFAM##$$/d' < $< > $@        
156
157 ifdown.8: ifup.8
158         ln -sf $< $@
159
160 %.5.ps: %.5
161         groff -mandoc -Tps $< > $@
162 %.8.ps: %.8
163         groff -mandoc -Tps $< > $@
164
165
166 Further, for convenience, we'll make use of two phony targets, [[clean]],
167 [[clobber]] and [[distclean]], which will delete working files, everything
168 that can be rebuilt with a [[make]] command, and everything that can be
169 rebuilt at all, respectively.
170
171 <<phony targets>>=
172 .PHONY : clean clobber
173
174 install :
175         install -m 0755 -d     ${BASEDIR}/sbin
176         install -m 0755 ifup   ${BASEDIR}/sbin
177         ln ${BASEDIR}/sbin/ifup ${BASEDIR}/sbin/ifdown  
178
179 clean :
180         rm -f *.aux *.toc *.log *.bbl *.blg *.ps *.eps *.pdf
181         rm -f *.o *.d $(patsubst %.defn,%.c,$(DEFNFILES)) *~
182         rm -f $(patsubst %.defn,%.man,$(DEFNFILES))
183         rm -f ifup ifdown interfaces.5 ifdown.8
184         rm -f ifupdown.dvi *.ps{,.gz}
185
186 clobber : clean
187         rm -f ifupdown.tex $(PERLFILES) $(CFILES) $(HFILES) $(DEFNFILES)
188
189 distclean : clobber
190         rm -f makecdep.sh makenwdep.sh Makefile
191
192
193 We have some fairly standard rules to build the printed version of the
194 source code using \LaTeX\ that are, unfortunately, not included in
195 [[make(1)]]'s builtin rules, so we'll note them here.
196
197 <<implicit rules>>=
198 %.tex : %.nw
199         noweave -delay -index -latex $< >$@
200
201 %.bbl : %.tex biblio.bib
202         latex $<
203         bibtex $(basename $<)
204
205 %.dvi : %.tex %.bbl
206         latex $<
207         latex $<
208
209 %.pdf : %.tex %.bbl
210         pdflatex $<
211         pdflatex $<
212
213 %.ps : %.dvi
214         dvips -o $@ $<
215
216 %.gz : %
217         gzip --best --stdout $< >$@
218
219
220 Additionally, some of [[make]]'s builtin rules are fairly
221 conservative, so we'll encourage it to use a more entertaining method
222 of compiling source code.
223
224 <<make options>>=
225 CFLAGS := -Wall -W -g -O2 -D'IFUPDOWN_VERSION="0.6.5"'
226 CC := gcc
227
228
229 \subsection{Graphics}
230
231 We include a few graphics (made using dia) in this document. We have to
232 express these fairly explicitly, unfortunately.
233
234 <<implicit rules>>=
235 %.eps : %.dia
236         dia --nosplash -e $@ $<
237
238 %.pdf : %.eps
239         gs -q -sDEVICE=pdfwrite -dNOPAUSE -sOutputFile=$@ - < $<
240 @
241
242 <<extra dependencies>>=
243 ifupdown.dvi: modules.eps execution.eps
244 ifupdown.ps: modules.eps execution.eps
245 ifupdown.pdf: modules.pdf execution.pdf
246 @
247
248 \subsection{Automatic Dependencies}
249
250 To build the system, we'll make use of some techniques discussed in
251 \cite{recursivemake} for determining dependencies. Namely, a number
252 of files will have an associated [[.d]] file containing dynamically
253 determined dependency information. The first such file we will construct
254 is the dependency information for [[noweb]] source files, which can be
255 identified by the [[.nw]] extension.
256
257 <<implicit rules>>=
258 %.d: %.nw makenwdep.sh
259         ./makenwdep.sh $< > $@
260 @
261
262 To construct the dependency information, we may use the [[noroots(1)]]
263 command to determine the \emph{root chunks} in the [[noweb]] source
264 (stripping the unwanted [[<<]] and [[>>]] markers as we go, and
265 denoting that in such a way that [[noweb]] doesn't mistakenly think
266 the [[sed]] command is a chunk reference itself), and then noting down
267 appropriate commands to construct the target.
268
269 <<makenwdep.sh>>=
270 <<parse makenwdep arguments>>
271
272 noroots $FILE | sed 's/^<''<\(.*\)>>$/\1/' |
273         while read chunk; do
274                 <<output dependency info for [[$chunk]]>>
275         done
276
277
278 Our dependency information is straightforward. To construct a file from
279 [[noweb]] source, we simply need to run [[notangle(1)]] over it. We add
280 a couple of extra tweaks in order to only update files that were actually
281 changed (the [[cpif(1)]] call), and to handle tabs properly.
282
283 We also need some extra things to take care of particular types of files.
284 In particular its important to have our scripts marked executable, so we
285 can use them as part of the build process itself, and it's also important
286 to have the dependency information for our C files (which are dealt with
287 next) included at some point.
288
289 <<output dependency info for [[$chunk]]>>=
290 printf "%s : %s\n" "$chunk" "$FILE"
291 case $chunk in
292         *.pl|*.sh)
293                 printf "\tnotangle -R\$@ \$< >\$@\n"
294                 printf "\tchmod 755 %s\n" "$chunk"
295                 ;;
296         *.c)
297                 printf "\tnotangle -L -R\$@ \$< | cpif \$@\n"
298                 printf "include ${chunk%.c}.d\n"
299                 ;;
300         *.h)
301                 printf "\tnotangle -L -R\$@ \$< | cpif \$@\n"
302                 ;;
303         *)
304                 printf "\tnotangle -t8 -R\$@ $< >\$@\n"
305                 ;;
306 esac
307
308
309 Finally, our fairly primitive argument parsing is simply:
310
311 <<parse makenwdep arguments>>=
312 FILE=$1
313
314 if [ "$FILE" = "" -o ! -f "$FILE" ]; then
315         echo "Please specify a .nw file"
316         exit 1
317 fi
318
319
320 We have a related system for object files generated from C source
321 code. Since each object file depends not only on its source, but also
322 the headers included in that source, we generate a [[.d]] file indicating
323 exactly which headers need to be checked.
324
325 <<implicit rules>>=
326 %.d: %.c makecdep.sh
327         ./makecdep.sh $< > $@
328
329
330 We can do this using [[gcc(1)]]'s convenient [[-MM -MG]] options,
331 which do exactly this, with the added proviso that the [[.d]] file
332 itself can possibly depend on any of the header files being modified
333 (and, in particular, [[#include]] lines being added or deleted).
334
335 <<makecdep.sh>>=
336 #!/bin/sh
337 <<parse makecdep arguments>>
338
339 gcc -MM -MG $FILE |
340   sed -e 's@^\(.*\)\.o:@\1.o \1.d:@'
341
342
343 \emph{Deja vu}, anyone?
344
345 <<parse makecdep arguments>>= 
346 FILE=$1
347 if [ "$FILE" = "" -o ! -f "$FILE" ]; then
348         echo "Please specify a .c file"
349         exit 1
350 fi
351 @
352
353 To include the generated dependencies in [[Makefile]], we have to
354 be a bit careful.  The problem here is that they should not be rebuild
355 when merely the cleaning of the source tree is asked for.  Any targets
356 ending in [[clean]], plus the [[clobber]] target prevent the inclusion
357 of the generated dependencies.
358
359 Unfortunately, [[make]] doesn't allow logical combinations within
360 [[ifeq]] and friends, so we have to simulate this.
361
362 <<generated dependency inclusion>>=
363 include-deps := YES
364 ifneq "" "$(filter %clean,$(MAKECMDGOALS))"
365 include-deps := NO
366 endif
367 ifeq "clobber" "$(MAKECMDGOALS)"
368 include-deps := NO
369 endif
370 @
371
372 Finally, include the dependency information:
373
374 <<generated dependency inclusion>>=
375 ifeq "$(strip $(include-deps))" "YES"
376 include ifupdown.d
377 endif
378 @
379
380 \section{Compile Time Configuration}
381
382 At compile time we need to determine all the possible address families
383 that may be used, and all the methods of setting up interfaces for
384 those address families, along with the various possible options
385 affecting each method.
386
387 Our key definition at this point is that of the [[address_family]]
388 structure, which encapsulates all the compile time information about
389 each address family.
390
391 <<type definitions>>=
392 typedef struct address_family address_family;
393
394
395 <<structure definitions>>=
396 struct address_family {
397         char *name;
398         int n_methods;
399         method *method;
400 };
401
402
403 Each defined address family will be included in the [[addr_fams]]
404 array, which becomes the \emph{raison d'\^etre} of the [[addrfam]]
405 module.
406
407 <<exported symbols>>=
408 extern address_family *addr_fams[];
409
410
411 Each address family incorporates a number of methods, which
412 encapsulate various ways of configuring an interface for a particular
413 address family. There are two definining components of a method: two
414 sets of commands to bring an interface up and down, and a number of
415 options for the commands.
416
417 \emph{NB: I expect this will be extended sooner or later to make the
418 options more flexible. Probably introducing some form of typing (for
419 example to convert netmasks from CIDR specs to dotted-quads, ie
420 /24~$\rightarrow$~255.255.255.0), and some form of matching to allow
421 multiple options to be deduced from a single configuration
422 statement. --- aj}
423
424 <<type definitions>>=
425 typedef struct method method;
426
427
428 <<structure definitions>>=
429 struct method {
430         char *name;
431         command_set *up, *down;
432 };
433
434
435 Each command set is implemented as a single function, accepting two
436 parameters: the definitions of the interface the commands should deal
437 with, and the function that should be used to execute them. See the
438 [[execute]] module for more details.
439
440 <<function type definitions>>=
441 typedef int (execfn)(char *command);
442 typedef int (command_set)(interface_defn *ifd, execfn *e);
443
444
445 As our compile-time configuration is done at, well, compile-time, there
446 is little need for functions in the actual module, and we can make do with
447 a single exported array.
448
449 <<addrfam.c>>=
450 #include <stdlib.h>
451 #include "header.h"
452
453 <<address family declarations>>
454
455 address_family *addr_fams[] = {
456         <<address family references>>
457         NULL
458 };
459
460
461 \subsection{Generating C Code}
462
463 Unfortunately, while the [[.defn]] representation is reasonably
464 convenient for human use, it's less convenient for a compiler. As
465 such, at build time, we will build a single structure of type
466 [[address_family]] in a separate module, and reference that from
467 [[addrfam.c]].
468
469 Naturally, we'll use a [[perl]] script to convert [[.defn]] files to C
470 code.
471
472 <<implicit rules>>=
473 %.c : %.defn defn2c.pl
474         ./defn2c.pl $< > $@
475
476
477 The functionality of our program is pretty basic: read from the file
478 specified as the argument, output to [[stdout]]; and correspondingly
479 the structure of the program is similarly simple. We make use of a
480 couple of global variables, a few helpful subroutines, and then build
481 our C program.
482
483 <<defn2c.pl>>=
484 #!/usr/bin/perl -w
485
486 use strict;
487
488 # declarations
489 <<defn2c variables>>
490
491 # subroutines
492 <<defn2c subroutines>>
493
494 # main code
495 <<output headers for address family>>
496 <<parse [[.defn]] file and output intermediate structures>>
497 <<output address family data structure>>
498
499
500 Clearly we need to reference some of the data structures we defined
501 above, so we can begin with the rather trivial:
502
503 <<output headers for address family>>=
504 print "#include \"header.h\"\n\n\n";
505
506
507 The overall purpose of the C code we're trying to construct is to
508 define a structure of type [[address_family]], and have it externally
509 visible. So we'd like to declare a statically-initialized structure of
510 this type, and be done with it.
511
512 To do this, however, we need to have some way of uniquely identifying
513 the structure to avoid naming conflicts. We'll do this by assuming we
514 have a previously initialized variable, [[$address_family]], and that
515 names of the form [[addr_foo]] won't be used elsewhere.
516
517 <<defn2c variables>>=
518 my $address_family = "";
519 @
520
521 We also need to reference an array of pointers to this address
522 family's [[method]]s, which will have to be initialized separately.
523 We'll assume that previous code will create such a structure, and call
524 it (imaginatively) [[methods]].
525
526 <<output address family data structure>>=
527 <<output [[methods]] data structure>>
528
529 print <<EOF;
530 address_family addr_${address_family} = {
531         "$address_family",
532         sizeof(methods)/sizeof(struct method),
533         methods
534 };
535 EOF
536
537
538 Our [[methods]] array will be a little more complicated to
539 construct. The first difficulty is that it will actually require some
540 state from having read the [[.defn]] file. To handle this, we'll
541 introduce a hash [[%methods]] that has the value [[1]] for each method
542 from the [[.defn]] file. We use a hash instead of a list because it
543 makes some error checking more convenient later, and since order
544 doesn't particularly matter.
545
546 <<defn2c variables>>=
547 my %methods = ();
548 @
549
550 We'll use standard names, such as [[foo_up]], [[foo_down]], and
551 [[foo_options]] for the various elements of each method which cannot
552 be defined inline. The two functions and the array will be declared
553 static to avoid name conflicts.
554
555 <<output [[methods]] data structure>>=
556 print "static method methods[] = {\n";
557 my $method;
558 foreach $method (keys %methods) {
559         print <<EOF;
560         {
561                 "$method",
562                 ${method}_up, ${method}_down,
563         },
564 EOF
565 }
566 print "};\n\n";
567
568
569 In a reasonably obvious manner we can then proceed to process the
570 [[.defn]] file to initialize the aforementioned variables, and to
571 output the method-specific functions and array. We'll begin by
572 defining a variable to keep track of the current line.
573
574 <<defn2c variables>>=
575 my $line = "";
576
577
578 Our semantics for this variable will be basically that it contains a
579 valid, meaningful input line. It won't be blank, or contain comments,
580 and if there aren't any more lines to be read, it will evaluate to
581 [[false]]. In order to keep these semantics, we'll use the subroutine
582 [[nextline]] to update it. (Since we'll later find we'll want to reuse
583 this subroutine, we'll keep it in a chunk of its own)
584
585 <<defn2c subroutines>>=
586 <<[[nextline]] subroutine>>
587
588
589 <<[[nextline]] subroutine>>=
590 sub nextline {
591         $line = <>;
592         while($line and ($line =~ /^#/ or $line =~ /^\s*$/)) {
593                 $line = <>;
594         }
595         if (!$line) { return 0; }
596         chomp $line;
597         while ($line =~ m/^(.*)\\$/) {
598                 my $addon = <>;
599                 chomp $addon;
600                 $line = $1 . $addon;
601         }
602         return 1;
603 }
604
605
606 Our high-level logic then looks basically like:
607
608 <<parse [[.defn]] file and output intermediate structures>>=
609 nextline;
610 while($line) {
611         <<parse a top-level section and output intermediate structures>>
612
613         # ...otherwise
614         die("Unknown command \"$line\"");
615 }
616 @
617
618 To make all this stuff easier, we'll use a `matching' function to help
619 with parsing lines: basically, given a line, a command, and possibly
620 an indentation prefix (eg [["    "]]). (As with [[nextline]], this will
621 also be useful to reuse, hence it has its own pair of chunks, too)
622
623 <<defn2c variables>>=
624 my $match = "";
625
626
627 <<defn2c subroutines>>=
628 <<[[match]] subroutine>>
629
630
631 <<[[match]] subroutine>>=
632 sub match {
633         my $line = $_[0];
634         my $cmd = "$_[1]" ? "$_[1]\\b\\s*" : "";;
635         my $indentexp = (@_ == 3) ? "$_[2]\\s+" : "";
636
637         if ($line =~ /^${indentexp}${cmd}(([^\s](.*[^\s])?)?)\s*$/) {
638                 $match = $1;
639                 return 1;
640         } else {
641                 return 0;
642         } 
643 }
644
645
646 Okay. So, the first line we expect to see is the name of the address
647 family we're defining.
648
649 <<parse a top-level section and output intermediate structures>>=
650 if (match($line, "address_family")) {
651         get_address_family $match;
652         next;
653 }
654
655
656 This is, as you'd imagine, pretty simple to deal with. We just need to
657 store the address family's name, and move on to the next line.
658
659 <<defn2c subroutines>>=
660 sub get_address_family {
661         $address_family = $_[0] if ($address_family eq "");
662         nextline;
663 }
664
665
666 Which brings us to determining the architecture.
667
668 <<parse a top-level section and output intermediate structures>>=
669 if (match($line, "architecture")) {
670         get_architecture $match;
671         next;
672 }
673
674
675 You'd never guess what, but it's just as easy as the address family thing
676 was.
677
678 <<defn2c subroutines>>=
679 sub get_architecture {
680         my $arch = $_[0];
681         die("architecture declaration appears too late") if (keys %methods);
682         print "#include \"arch${arch}.h\"\n\n\n";
683         nextline;
684 }
685
686
687 Which leaves us with the hard bit, actually creating the functions and
688 array for each method.
689
690 <<parse a top-level section and output intermediate structures>>=
691 if (match($line, "method")) {
692         get_method $match;
693         next;
694 }
695 @
696
697 The basic premise is to check for each of our options in a given
698 order: if they don't match, then we can presume they don't exist ---
699 any errors will be reported when the main function finds something
700 weird going on. All we really have to take care of so far is ensuring
701 an appropriate level of indentation, and that we're not defining the
702 same method twice.
703
704 <<defn2c subroutines>>=
705 sub get_method {
706         my $method = $_[0];
707         my $indent = ($line =~ /(\s*)[^\s]/) ? $1 : "";
708
709         die "Duplicate method $method\n" if ($methods{$method}++);
710
711         nextline;
712         <<output code for description>>
713         <<output code for options list>>
714         <<output code for up commands>>
715         <<output code for down commands>>
716 }
717
718
719 The description and options sections are just documentation chunks,
720 and hence aren't at all relevant for the C code.
721
722 <<output code for description>>=
723 if (match($line, "description", $indent)) {
724         skip_section();
725 }
726
727
728 <<output code for options list>>=
729 if (match($line, "options", $indent)) {
730         skip_section();
731 }
732
733
734 Skipping a section is fairly easy: we just need to check alignments. This is
735 yet another subroutine that'll come in handy elsewhere.
736
737 <<defn2c subroutines>>=
738 <<[[skip_section]] subroutine>>
739
740
741 <<[[skip_section]] subroutine>>=
742 sub skip_section {
743         my $struct = $_[0];
744         my $indent = ($line =~ /(\s*)[^\s]/) ? $1 : "";
745
746         1 while (nextline && match($line, "", $indent));
747 }
748
749
750 Checking the various relevant components of each method is fairly
751 simple: we need to see if it exists, and if it does, parse and output
752 it, while if it doesn't, we need to output a place holder.
753
754 <<output code for up commands>>=
755 if (match($line, "up", $indent)) {
756         get_commands(${method}, "up");
757 } else {
758         print "static int ${method}_up(interface_defn ifd) { return 0; }\n"
759 }
760
761
762 <<output code for down commands>>=
763 if (match($line, "down", $indent)) {
764         get_commands(${method}, "down");
765 } else {
766         print "static int ${method}_down(interface_defn ifd) { return 0; }\n"
767 }
768 @
769
770 <<defn2c subroutines>>=
771 sub get_commands {
772         my $method = $_[0];
773         my $mode = $_[1];
774         my $function = "${method}_${mode}";
775         my $indent = ($line =~ /(\s*)[^\s]/) ? $1 : "";
776
777         print "static int ${function}(interface_defn *ifd, execfn *exec) {\n";
778
779         while (nextline && match($line, "", $indent)) {
780                 if ( $match =~ /^(.*[^\s])\s+if\s*\((.*)\)\s*$/ ) {
781                         print "if ( $2 ) {\n";
782                         print "  if (!execute(\"$1\", ifd, exec)) return 0;\n";
783                         print "}\n";
784                 } elsif ( $match =~ /^(.*[^\s])\s+elsif\s*\((.*)\)\s*$/ ) {
785                         print "else if ( $2 ) {\n";
786                         print "  if (!execute(\"$1\", ifd, exec)) return 0;\n";
787                         print "}\n";
788                 } elsif ( $match =~ /^(.*[^\s])\s*$/ ) {
789                         print "{\n";
790                         print "  if (!execute(\"$1\", ifd, exec)) return 0;\n";
791                         print "}\n";
792                 }
793         }
794
795         print "return 1;\n";
796         print "}\n";
797 }
798
799
800 \subsection{Building Manual Pages}
801
802 So having C code is all very well, but if you want to ignore all user
803 problems with a casual ``RTFM!'' there has to be some semblance of an
804 M for them to R. So we need a script to generate some useful
805 descriptions of the various methods.
806
807 We'll achieve this by making another Perl script, [[defn2man.pl]],
808 which will generate fragments of [[troff]] that can be catted together
809 with a general overview of [[ifupdown]] to produce real manpages.
810
811 <<implicit rules>>=
812 %.man: %.defn defn2man.pl
813         ./defn2man.pl $< > $@
814
815
816 So we'll use a similar structure to [[defn2c.pl]].
817
818 <<defn2man.pl>>=
819 #!/usr/bin/perl -w
820
821 use strict;
822
823 # declarations
824 <<defn2man variables>>
825
826 # subroutines
827 <<defn2man subroutines>>
828
829 # main code
830 <<parse [[.defn]] file and output manpage fragment>>
831
832
833 As predicted, we'll also incorporate [[nextline]], [[match]] and
834 [[skip_section]]:
835
836 <<defn2man variables>>=
837 my $line;
838 my $match;
839
840
841 <<defn2man subroutines>>=
842 <<[[nextline]] subroutine>>
843 <<[[match]] subroutine>>
844 <<[[skip_section]] subroutine>>
845
846
847 Now we'll have a slightly different structure to the program itself
848 this time, since we need to do things pretty much in order for
849 outputting the manpage. This imposes stricter ordering requirements on
850 the [[.defn]] files than [[defn2c]] did.
851
852 <<parse [[.defn]] file and output manpage fragment>>=
853 nextline;
854 if ($line and match($line, "address_family")) {
855         get_address_family $match;
856 } else {
857         die "address_family must be listed first\n";
858 }
859 if ($line and match($line, "architecture")) {
860         get_architecture $match;
861 }
862 while ($line and match($line, "method")) {
863         get_method $match;
864 }
865
866
867 Okay, so it wasn't \emph{that} different from what we had before. Sue
868 me.
869
870 The [[get_address_family]] and [[get_architecture]] subroutines are
871 fairly straight forward:
872
873 <<defn2man subroutines>>=
874 sub get_address_family {
875         print ".SH " . uc($match) . " ADDRESS FAMILY\n";
876         print "This section documents the methods available in the\n";
877         print "$match address family.\n";
878         nextline;
879 }
880
881
882 <<defn2man subroutines>>=
883 sub get_architecture {
884         # no op
885         nextline;
886 }
887
888
889 Which only leaves extracting the description and options for each
890 method. And, of course, this imposes less restrictions of the
891 [[.defn]] file than [[defn2c.pl]] did. It's a crazy old world.
892
893 <<defn2man subroutines>>=
894 sub get_method {
895         my $method = shift;
896         my $indent = ($line =~ /(\s*)\S/) ? $1 : "";
897         my $description = "";
898         my @options = ();
899
900         nextline;
901         while ($line and match($line, "", $indent)) {
902                 if (match($line, "description", $indent)) {
903                         $description = get_description();
904                 } elsif (match($line, "options", $indent)) {
905                         @options = get_options();
906                 } else {
907                         skip_section;
908                 }
909         }
910
911         <<output [[$method]] introduction man fragment>>
912         <<output [[$description]] man fragment>>
913         <<output [[@options]] man fragment>>
914 }
915 @
916
917 <<output [[$method]] introduction man fragment>>=
918 print ".SS The $method Method\n";
919
920
921 Okay. Now our [[$description]] is just the description with any [['\n']]
922 characters it may've had, but without the leading spaces.
923
924 <<defn2man subroutines>>=
925 sub get_description {
926         my $desc = "";
927         my $indent = ($line =~ /(\s*)\S/) ? $1 : "";
928         while(nextline && match($line, "", $indent)) {
929                 $desc .= "$match\n";
930         }
931         return $desc;
932 }
933
934
935 We're actually going to be a little tricky here, and allow some formatting
936 in our descriptions. Basically, we'll allow bold and italic encoding
937 to be denoted by [[*bold*]] and [[/italics/]] in the wonderful Usenet
938 tradition. As such, we'll use a cute little function to convert the
939 Usenet style to \emph{roff}. We'll also take care not to do this conversion
940 within words (for things like [[/etc/hosts]], eg). Voila:
941
942 <<defn2man subroutines>>=
943 sub usenet2man {
944         my $in = shift;
945         my $out = "";
946
947         $in =~ s/\s+/ /g;
948         while ($in =~ m%^([^*/]*)([*/])([^*/]*)([*/])(.*)$%s) {
949                 my ($pre, $l, $mid, $r, $post) = ($1, $2, $3, $4, $5);
950                 if ($l eq $r && " $pre"  =~ m/[[:punct:][:space:]]$/ 
951                              && "$post " =~ m/^[[:punct:][:space:]]/) {
952                         $out .= $pre;
953                         $out .= ($l eq "*" ? '\fB' : '\fI') . $mid . '\fP';
954                         ($in = $post) =~ s/^\s+/ /;
955                 } else {
956                         $out .= $pre . $l;
957                         $in = $mid . $r . $post;
958                 }
959         } 
960         return $out . $in;
961 }
962 @
963
964 The only further thing to note about this is that we're being careless
965 and ignoring the possibility of \emph{roff} escape sequences in the input. But
966 since this is for internal use only, well, too bad. So here we go:
967
968 <<output [[$description]] man fragment>>=
969 if ($description ne "") {
970         print usenet2man($description) . "\n";
971 } else {
972         print "(No description)\n";
973 }
974
975
976 Damn that was fun.
977
978 Reading the options is almost exactly the same as the description,
979 except we want a list instead of just a string.
980
981 <<defn2man subroutines>>=
982 sub get_options {
983         my @opts = ();
984         my $indent = ($line =~ /(\s*)\S/) ? $1 : "";
985         while(nextline && match($line, "", $indent)) {
986                 push @opts, $match;
987         }
988         return @opts;
989 }
990
991
992 Output is slightly more complicated, but not too much so.
993
994 <<output [[@options]] man fragment>>=
995 print ".PP\n";
996 print ".B Options\n";
997 print ".RS\n";
998 if (@options) {
999         foreach my $o (@options) {
1000                 if ($o =~ m/^\s*(\S*)\s*(.*)\s+--\s+(\S.*)$/) {
1001                         my $opt = $1;
1002                         my $optargs = $2;
1003                         my $dsc = $3;
1004                         print ".TP\n";
1005                         print ".BI $opt";
1006                         print " \" $optargs\"" unless($optargs =~ m/^\s*$/);
1007                         print "\n";
1008                         print usenet2man($dsc) . "\n";
1009                 } else {
1010                         print ".TP\n";
1011                         print ".B $o\n";
1012                 }
1013         }
1014 } else {
1015         print ".TP\n";
1016         print "(No options)\n";
1017 }
1018 print ".RE\n";
1019
1020
1021 \section{Run-time Configuration}
1022
1023 Our module is of the usual form, and we'll make use of a few fairly standard
1024 headers. Please move along, there's nothing to see here.
1025
1026 <<config.c>>=
1027 <<config headers>>
1028 <<config function declarations>>
1029 <<config functions>>
1030
1031
1032 <<config headers>>=
1033 #include <stdlib.h>
1034 #include <stdio.h>
1035 #include <string.h>
1036 #include <errno.h>
1037 #include <assert.h>
1038
1039
1040 We'll also make use of some of our other modules. This is, after all,
1041 why we had a single header in the first place.
1042
1043 <<config headers>>=
1044 #include "header.h"
1045
1046
1047 The key function we're interested in defining here is
1048 [[read_interfaces()]], which will (wait for it) read an interfaces
1049 file. The intention is to make it really easy to deal with the
1050 vagaries of [[/etc/network/interfaces]] anywhere else.
1051
1052 So the first question we need to deal with is ``What's a convenient
1053 form for other functions which deal with interfaces?'' Well, our
1054 answer to that is basically:
1055
1056 \begin{enumerate}
1057         \item an array of interface names that should be brought up at
1058         bootup.
1059
1060         \item a singly linked list to represent the various mappings.
1061
1062         \item another singly linked list to represent the interface
1063         definitions themselves.
1064 \end{enumerate}
1065
1066  These are almost in exact correspondence with the original file.
1067
1068 <<type definitions>>=
1069 typedef struct interfaces_file interfaces_file;
1070
1071
1072 <<structure definitions>>=
1073 struct interfaces_file {
1074         allowup_defn *allowups;
1075         interface_defn *ifaces;
1076         mapping_defn *mappings;
1077 };
1078 @
1079
1080 So, at run-time, we first need a way of dealing with the [[auto]] and
1081 [[allow-*]] lines. We'll treat [[allow-auto]] and [[auto]] as equivalent,
1082 making that pretty straightforward:
1083
1084 <<type definitions>>=
1085 typedef struct allowup_defn allowup_defn;
1086 @
1087
1088 <<structure definitions>>=
1089 struct allowup_defn {
1090         allowup_defn *next;
1091
1092         char *when;
1093         int max_interfaces;
1094         int n_interfaces;
1095         char **interfaces;
1096 };
1097
1098
1099 We also require a way of representing each interface listed in the
1100 configuration file. This naturally needs to reference an address family
1101 and method, and all the options a user may specify about an interface.
1102
1103 <<type definitions>>=
1104 typedef struct interface_defn interface_defn;
1105
1106
1107 <<structure definitions>>=
1108 struct interface_defn {
1109         interface_defn *next;
1110
1111         char *logical_iface;
1112         char *real_iface;
1113
1114         address_family *address_family;
1115         method *method;
1116
1117         int automatic;
1118
1119         int max_options;
1120         int n_options;
1121         variable *option;
1122 };
1123 @
1124
1125 The last component in the above, the options, is represented by a
1126 series of name/value pairs, as follows:
1127
1128 <<type definitions>>=
1129 typedef struct variable variable;
1130
1131
1132 <<structure definitions>>=
1133 struct variable {
1134         char *name;
1135         char *value;
1136 };
1137
1138
1139 In addition, we want to represent each mapping in the configuration
1140 file. This is somewhat simpler, since each mapping is entirely self
1141 contained, and doesn't need to reference previously determined address
1142 families or methods or anything.
1143
1144 <<type definitions>>=
1145 typedef struct mapping_defn mapping_defn;
1146
1147
1148 <<structure definitions>>=
1149 struct mapping_defn {
1150         mapping_defn *next;
1151
1152         int max_matches;
1153         int n_matches;
1154         char **match;
1155
1156         char *script;
1157
1158         int max_mappings;
1159         int n_mappings;
1160         char **mapping;
1161 };
1162
1163
1164 We can thus begin to instantiate our actual function. What we want is
1165 something that, given the name of a file, will produce the appropriate
1166 linked list of interfaces defined in it, or possibly give some sort of
1167 helpful error message. Pretty simple, hey?
1168
1169 <<exported symbols>>=
1170 interfaces_file *read_interfaces(char *filename);
1171
1172
1173 <<config functions>>=
1174 interfaces_file *read_interfaces(char *filename) {
1175         <<variables local to read interfaces>>
1176         interfaces_file *defn;
1177
1178         <<allocate defn or [[return NULL]]>>
1179         <<open file or [[return NULL]]>>
1180
1181         while (<<we've gotten a line from the file>>) {
1182                 <<process the line>>
1183         }
1184         if (<<an error occurred getting the line>>) {
1185                 <<report internal error and die>>
1186         }
1187
1188         <<close file>>
1189
1190         return defn;
1191 }
1192
1193
1194 <<allocate defn or [[return NULL]]>>=
1195 defn = malloc(sizeof(interfaces_file));
1196 if (defn == NULL) {
1197         return NULL;
1198 }
1199 defn->allowups = NULL;
1200 defn->mappings = NULL;
1201 defn->ifaces = NULL;
1202
1203
1204 \subsection{File Handling}
1205
1206 So, the first and most obvious thing to deal with is the file
1207 handling. Nothing particularly imaginative here.
1208
1209 <<variables local to read interfaces>>=
1210 FILE *f;
1211 int line;
1212
1213
1214 <<open file or [[return NULL]]>>=
1215 f = fopen(filename, "r");
1216 if ( f == NULL ) return NULL;
1217 line = 0;
1218 @
1219
1220 <<close file>>=
1221 fclose(f);
1222 line = -1;
1223 @
1224
1225 \subsection{Line Parsing}
1226
1227 Our next problem is to work out how to read a single line from our
1228 input file. While this is nominally easy, we also want to deal nicely
1229 with things like continued lines, comments, and very long lines.
1230
1231 So we're going to have to write and make use of a complicated little
1232 function, which we'll imaginatively call [[get_line()]]. It will need
1233 a pointer to the file it's reading from, as well as a buffer to store
1234 the line it finds. Since this buffer's size can't be known in advance
1235 we'll need to make it [[realloc()]]-able, which means we need to pass
1236 around references to both the buffer's location (which may change),
1237 and it's size (which probably will). Our function declaration is thus:
1238
1239 <<config function declarations>>=
1240 static int get_line(char **result, size_t *result_len, FILE *f, int *line);
1241
1242
1243 To use it, we'll need a couple of variables to stores the buffer's
1244 location, and it's current length.
1245
1246 <<variables local to read interfaces>>=
1247 char *buf = NULL;
1248 size_t buf_len = 0;
1249
1250
1251 Given these, and presuming we can actually implement the function, our
1252 key chunk can thus be implemented simply as:
1253
1254 <<we've gotten a line from the file>>=
1255 get_line(&buf,&buf_len,f,&line)
1256
1257
1258 We'll also add the requirement that errors are indicated by the
1259 [[errno]] variable being non-zero, which is usual and reasonable for
1260 all the circumstances where [[get_line()]] might have problems.
1261
1262 <<config headers>>=
1263 #include <errno.h>
1264
1265
1266 <<an error occurred getting the line>>=
1267 ferror(f) != 0
1268
1269
1270 Actually defining the function is, as you'd probably imagine, a little
1271 more complicated. We begin by reading a line from the file. If it was
1272 a comment (that is, it has a [[#]] character at the first non-blank
1273 position) then we try again. Otherwise, if the line is continued
1274 (indicated by a [[\]] character at the very end of the line) we append
1275 the next line to the buffer. We go to a little bit of effort to trim
1276 whitespace, and finally return a boolean result indicating whether we
1277 got a line or not.
1278
1279 <<config functions>>=
1280 static int get_line(char **result, size_t *result_len, FILE *f, int *line) {
1281         <<variables local to get line>>
1282
1283         do {
1284                 <<clear buffer>>
1285                 <<append next line to buffer, or [[return 0]]>>
1286                 <<trim leading whitespace>>
1287         } while (<<line is a comment>>);
1288
1289         while (<<buffer is continued>>) {
1290                 <<remove continuation mark>>
1291                 <<append next line to buffer, or [[return 0]]>>
1292         }
1293
1294         <<trim trailing whitespace>>
1295
1296         return 1;
1297 }
1298
1299
1300 In order to do string concatenation efficiently, we'll keep track of
1301 where the end of the line so far is --- this is thus where the
1302 terminating [[NUL]] will be by the end of the function.
1303
1304 <<variables local to get line>>=
1305 size_t pos;
1306
1307
1308 We can thus clear the buffer by simply resetting where we append new
1309 text to the beginning of the buffer. What could be simpler?
1310
1311 <<clear buffer>>=
1312 pos = 0;
1313
1314
1315 We'll be making use of the [[fgets()]] function to read the line
1316 (rather than, say, [[fgetc()]]) so to get an entire line we may have
1317 to make multiple attempts (if the line is bigger than our
1318 buffer). Realising this, and the fact that we may not have any
1319 allocated space for our buffer initially, we need a loop something
1320 like:
1321
1322 <<append next line to buffer, or [[return 0]]>>=
1323 do {
1324         <<reallocate buffer as necessary, or [[return 0]]>>
1325         <<get some more of the line, or [[return 0]]>>
1326 } while(<<the line isn't complete>>);
1327
1328 <<remove trailing newline>>
1329
1330 (*line)++;
1331
1332 assert( (*result)[pos] == '\0' );
1333
1334
1335 When reallocating the buffer, we need to make sure it increases in
1336 chunks large enough that we don't have to do this too often, but not
1337 so huge that we run out of memory just to read an 81 character line.
1338 We'll use two fairly simple heuristics for this: if we've got room to
1339 add no more than 10 characters, we may as well reallocate the buffer,
1340 and when reallocating, we want to more or less double the buffer, but
1341 we want to at least add 80 characters. So we do both.
1342
1343 <<reallocate buffer as necessary, or [[return 0]]>>=
1344 if (*result_len - pos < 10) {
1345         char *newstr = realloc(*result, *result_len * 2 + 80);
1346         if (newstr == NULL) {
1347                 return 0;
1348         }
1349         *result = newstr;
1350         *result_len = *result_len * 2 + 80;
1351 }
1352
1353
1354 The only time we need to keep reading is when the buffer wasn't big
1355 enough for the entire line. This is indicated by a full buffer, with
1356 no newline at the end. There is, actually, one case where this can
1357 happen legitimately --- where the last line of the file is
1358 \emph{exactly} the length of the buffer. We need to detect this
1359 because [[fgets()]] will return [[NULL]] and indicate that it's hit
1360 the end of the file, but we won't want to indicate that until the
1361 \emph{next} time we try to get a line. Complicated, isn't it?
1362
1363 <<the line isn't complete>>=
1364 pos == *result_len - 1 && (*result)[pos-1] != '\n'
1365
1366
1367 So having thought through all that, actually working with [[fgets()]]
1368 is fairly simple, especially since we deal with the actual errors
1369 elsewhere. All we need to do is make the call, update [[pos]] and
1370 check that the problems [[fgets()]] may have actually bother us.
1371
1372 <<get some more of the line, or [[return 0]]>>=
1373 if (!fgets(*result + pos, *result_len - pos, f)) {
1374         if (ferror(f) == 0 && pos == 0) return 0;
1375         if (ferror(f) != 0) return 0;
1376 }
1377 pos += strlen(*result + pos);
1378
1379
1380 [[fgets()]] leaves a [[\n]] in our buffer in some cases. We're never
1381 actually interested in it, however, so it's a good move to get rid of
1382 it.
1383
1384 <<remove trailing newline>>=
1385 if (pos != 0 && (*result)[pos-1] == '\n') {
1386         (*result)[--pos] = '\0';
1387 }
1388
1389
1390
1391 Pretty simple, hey? Now the next thing we want to do is get rid of
1392 some of the whitespace lying about. This is all pretty basic, and just
1393 involves finding where the whitespace begins and ends, and, well,
1394 getting rid of it.
1395
1396 <<config headers>>=
1397 #include <ctype.h>
1398
1399
1400 <<trim leading whitespace>>=
1401
1402         int first = 0; 
1403         while (isspace((*result)[first]) && (*result)[first]) {
1404                 first++;
1405         }
1406
1407         memmove(*result, *result + first, pos - first + 1);
1408         pos -= first;
1409 }
1410
1411
1412 <<trim trailing whitespace>>=
1413 while (isspace((*result)[pos-1])) { /* remove trailing whitespace */
1414         pos--;
1415 }
1416 (*result)[pos] = '\0';
1417
1418
1419 As we mentioned earlier, a line is a comment iff it's first character
1420 is a [[#]] symbol. Similarly, it's continued iff it's very last
1421 character is a [[\]]. And, rather obviously, if we want to remove a
1422 single trailing [[\]], we can do so by changing it to a [[NUL]].
1423
1424 <<line is a comment>>=
1425 (*result)[0] == '#'
1426
1427
1428 <<buffer is continued>>=
1429 (*result)[pos-1] == '\\'
1430
1431
1432 <<remove continuation mark>>=
1433 (*result)[--pos] = '\0';
1434
1435
1436 \subsection{Line Processing}
1437
1438 So. We've gone to a lot of trouble to get a line that we can parse
1439 with a snap of our fingers, so we probably better jump to it, to mix
1440 some \emph{clich\'e's}.
1441
1442 We have two alternative bits of state to maintain between lines: either
1443 what interface we're currently defining, or what mapping we're currently
1444 defining.
1445
1446 <<variables local to read interfaces>>=
1447 interface_defn *currif = NULL;
1448 mapping_defn *currmap = NULL;
1449 enum { NONE, IFACE, MAPPING } currently_processing = NONE;
1450
1451
1452 Since our configuration files are pretty basic, we can work out what
1453 any particular line means based on the first word in it. To cope with
1454 this, we'll thus make use of a couple of variables, one to store the
1455 first word, and the other to store the rest of the line.
1456
1457 <<variables local to read interfaces>>=
1458 char firstword[80];
1459 char *rest;
1460
1461
1462 To initialize these variables we'll make use of a function I'm overly
1463 fond of called [[next_word()]]. It copies the first word in a string
1464 to a given buffer, and returns a pointer to the rest of the buffer.
1465
1466 <<config function declarations>>=
1467 static char *next_word(char *buf, char *word, int maxlen);
1468 @
1469
1470 <<config functions>>=
1471 static char *next_word(char *buf, char *word, int maxlen) {
1472         if (!buf) return NULL;
1473         if (!*buf) return NULL;
1474
1475         while(!isspace(*buf) && *buf) {
1476                 if (maxlen-- > 1) *word++ = *buf;
1477                 buf++;
1478         }
1479         if (maxlen > 0) *word = '\0';
1480
1481         while(isspace(*buf) && *buf) buf++;
1482
1483         return buf;
1484 }
1485
1486
1487 So after all this, there are basically three different sorts of line
1488 we can get: the start of a new interface, the start of a new mapping,
1489 or an option for whatever interface we're currently working with.
1490 Note that we check for blank lines, but \emph{not} for options with
1491 empty values.  This has to be done on a case-by-case basis.
1492
1493 <<process the line>>=
1494 rest = next_word(buf, firstword, 80);
1495 if (rest == NULL) continue; /* blank line */
1496
1497 if (strcmp(firstword, "mapping") == 0) {
1498         <<process [[mapping]] line>>
1499         currently_processing = MAPPING;
1500 } else if (strcmp(firstword, "iface") == 0) {
1501         <<process [[iface]] line>>
1502         currently_processing = IFACE;
1503 } else if (strcmp(firstword, "auto") == 0) {
1504         <<process [[auto]] line>>
1505         currently_processing = NONE;
1506 } else if (strncmp(firstword, "allow-", 6) == 0 && strlen(firstword) > 6) {
1507         <<process [[allow-]] line>>
1508         currently_processing = NONE;
1509 } else {
1510         <<process option line>>
1511 }
1512
1513
1514 <<process option line>>=
1515 switch(currently_processing) {
1516         case IFACE:
1517                 <<process iface option line>>
1518                 break;
1519         case MAPPING:
1520                 <<process mapping option line>>
1521                 break;
1522         case NONE:
1523         default:
1524                 <<report bad option and die>>
1525 }
1526
1527
1528 \subsubsection{Mapping Line}
1529
1530 Declaring a new mapping is reasonably copewithable --- we need to process
1531 a few things, but they're reasonably easy to handle.
1532
1533 The main weirdness is that we're processing the [[mapping]] line itself
1534 and the rest of the stanza in separate blocks of code. So this first
1535 chunk just needs to do the basics of initialising the data structure,
1536 but can't really fill in all that much of it.
1537
1538 <<process [[mapping]] line>>=
1539 <<allocate new mapping>>
1540 <<parse mapping interfaces>>
1541 <<set other mapping options to defaults>>
1542 <<add to list of mappings>>
1543
1544
1545 <<allocate new mapping>>=
1546 currmap = malloc(sizeof(mapping_defn));
1547 if (currmap == NULL) {
1548         <<report internal error and die>>
1549 }
1550
1551
1552 <<parse mapping interfaces>>=
1553 currmap->max_matches = 0;
1554 currmap->n_matches = 0;
1555 currmap->match = NULL;
1556
1557 while((rest = next_word(rest, firstword, 80))) {
1558         if (currmap->max_matches == currmap->n_matches) {
1559                 char **tmp;
1560                 currmap->max_matches = currmap->max_matches * 2 + 1;
1561                 tmp = realloc(currmap->match, 
1562                         sizeof(*tmp) * currmap->max_matches);
1563                 if (tmp == NULL) {
1564                         currmap->max_matches = (currmap->max_matches - 1) / 2;
1565                         <<report internal error and die>>
1566                 }
1567                 currmap->match = tmp;
1568         }
1569
1570         currmap->match[currmap->n_matches++] = strdup(firstword);
1571 }
1572
1573
1574 <<set other mapping options to defaults>>=
1575 currmap->script = NULL;
1576
1577 currmap->max_mappings = 0;
1578 currmap->n_mappings = 0;
1579 currmap->mapping = NULL;
1580
1581
1582 <<add to list of mappings>>=
1583 {
1584         mapping_defn **where = &defn->mappings;
1585         while(*where != NULL) {
1586                 where = &(*where)->next;
1587         }
1588         *where = currmap;
1589         currmap->next = NULL;
1590 }
1591
1592
1593 So that's that. But as mentioned, we also need to cope with the options
1594 within the stanza, as well as the lead in. As before, it's not really
1595 complicated, and we do it thusly:
1596
1597 <<process mapping option line>>=
1598 if (strcmp(firstword, "script") == 0) {
1599         <<handle [[script]] line>>
1600 } else if (strcmp(firstword, "map") == 0) {
1601         <<handle [[map]] line>>
1602 } else {
1603         <<report bad option and die>>
1604 }
1605
1606
1607 <<handle [[script]] line>>=
1608 if (currmap->script != NULL) {
1609         <<report duplicate script in mapping and die>>
1610 } else {
1611         currmap->script = strdup(rest);
1612 }
1613
1614
1615 <<handle [[map]] line>>=
1616 if (currmap->max_mappings == currmap->n_mappings) {
1617         char **opt;
1618         currmap->max_mappings = currmap->max_mappings * 2 + 1;
1619         opt = realloc(currmap->mapping, sizeof(*opt) * currmap->max_mappings);
1620         if (opt == NULL) {
1621                 <<report internal error and die>>
1622         }
1623         currmap->mapping = opt;
1624 }
1625 currmap->mapping[currmap->n_mappings] = strdup(rest);
1626 currmap->n_mappings++;
1627
1628
1629 \subsubsection{Interface line}
1630
1631 Declaring a new interface follows the same pattern, but is somewhat more
1632 interesting and some more complicated data structures are involved.
1633
1634 <<process [[iface]] line>>=
1635 {
1636         <<variables local to process [[iface]] line>>
1637
1638         <<allocate new interface>>
1639
1640         <<parse interface settings>>
1641
1642         <<set iface name>>
1643         <<set address family>>
1644         <<set method>>
1645         <<set other interface options to defaults>>
1646
1647         <<add to list of interfaces>>
1648 }
1649
1650
1651 We'll deal with each of these phases one by one and pretty much in
1652 order, so prepare yourself for the intense excitement of memory
1653 allocation!
1654
1655 <<allocate new interface>>=
1656 currif = malloc(sizeof(interface_defn));
1657 if (!currif) {
1658         <<report internal error and die>>
1659 }
1660
1661
1662 When we introduce a new interface, we simultaneously name the
1663 interface, the address family, and the method. We cope with this by,
1664 well, getting somewhere to store each of them, and then, well, storing
1665 them.
1666
1667 <<variables local to process [[iface]] line>>=
1668 char iface_name[80];
1669 char address_family_name[80];
1670 char method_name[80];
1671
1672
1673 <<parse interface settings>>=
1674 rest = next_word(rest, iface_name, 80);
1675 rest = next_word(rest, address_family_name, 80);
1676 rest = next_word(rest, method_name, 80);
1677
1678 if (rest == NULL) {
1679         <<report too few parameters for iface line and die>>
1680 }
1681
1682 if (rest[0] != '\0') {
1683         <<report too many parameters for iface line and die>>
1684 }
1685
1686
1687 We then want to store the interface name.
1688
1689 <<set iface name>>=
1690 currif->logical_iface = strdup(iface_name);
1691 if (!currif->logical_iface) {
1692         <<report internal error and die>>
1693 }
1694
1695
1696 Setting the address family is a little more involved, because it's not
1697 very useful to know what the name of the address family is, you really
1698 want to know all the details recorded in the appropriate
1699 [[address_family]] structure. So we'll make use of a little helper
1700 function, called [[get_address_family()]] to convert the useless
1701 string, to the hopefully less useless structure.
1702
1703 <<config function declarations>>=
1704 static address_family *get_address_family(address_family *af[], char *name);
1705
1706
1707 <<set address family>>=
1708 currif->address_family = get_address_family(addr_fams, address_family_name);
1709 if (!currif->address_family) {
1710         <<report unknown address family and die>>
1711 }
1712
1713
1714 Of course, we probably need to actually implement the function too. We
1715 won't do anything particularly fancy here, just a simple linear
1716 search. \emph{Should this really be here, or an exported symbol from
1717 [[addrfam.c]]? --- aj}
1718
1719 <<config functions>>=
1720 static address_family *get_address_family(address_family *af[], char *name) {
1721         int i;
1722         for (i = 0; af[i]; i++) {
1723                 if (strcmp(af[i]->name, name) == 0) {
1724                         return af[i];
1725                 }
1726         }
1727         return NULL;
1728 }
1729 @
1730
1731 We do something incredibly similar when dealing with the method the
1732 user wishes to use, and we do it for incredibly similar reasons. Again
1733 we declare a cute little helper function, this time imaginatively
1734 called [[get_method()]], and then go and use it and implement in
1735 almost exactly the same way as before. I told you this was going to be
1736 a thrill. \emph{The same note applies here, too --- aj}
1737
1738 <<config function declarations>>=
1739 static method *get_method(address_family *af, char *name);
1740
1741
1742 <<set method>>=
1743 currif->method = get_method(currif->address_family, method_name);
1744 if (!currif->method) {
1745         <<report unknown method and die>>
1746         return NULL; /* FIXME */
1747 }
1748 @
1749
1750 <<config functions>>=
1751 static method *get_method(address_family *af, char *name) {
1752         int i;
1753         for (i = 0; i < af->n_methods; i++) {
1754                 if (strcmp(af->method[i].name, name) == 0) {
1755                         return &af->method[i];
1756                 }
1757         }
1758         return NULL;
1759 }
1760 @
1761
1762 You'll continue to be enthralled as we set the remaining options to
1763 some default values.
1764
1765 <<set other interface options to defaults>>=
1766 currif->automatic = 1;
1767 currif->max_options = 0;
1768 currif->n_options = 0;
1769 currif->option = NULL;
1770
1771
1772 Since we want to keep the interfaces in order, we have to go all the
1773 way to the end of the list of interfaces to add the new interface, and
1774 we can hence set the [[next]] pointer to NULL in all cases. Gee. Whiz.
1775
1776 Actually, I'm selling this a little short. We also want to make sure
1777 we don't try instantiating the same interface twice or anything. So we
1778 take care of that too. There now. Didn't that just get the adrenalin
1779 pumping?
1780
1781 <<add to list of interfaces>>=
1782 {
1783         interface_defn **where = &defn->ifaces; 
1784         while(*where != NULL) {
1785                 if (duplicate_if(*where, currif)) {
1786                         <<report duplicate interface and die>>
1787                 }
1788                 where = &(*where)->next;
1789         }
1790
1791         *where = currif;
1792         currif->next = NULL;
1793 }
1794
1795
1796 Duplicate interfaces are interfaces that have the same name and the
1797 same address family. Nothing more complicated than that.
1798
1799 <<config function declarations>>=
1800 static int duplicate_if(interface_defn *ifa, interface_defn *ifb);
1801
1802
1803 <<config functions>>=
1804 static int duplicate_if(interface_defn *ifa, interface_defn *ifb) {
1805         if (strcmp(ifa->logical_iface, ifb->logical_iface) != 0) return 0;
1806         if (ifa->address_family != ifb->address_family) return 0;
1807         return 1;
1808 }
1809
1810
1811 Dealing with the per-interface options is the next thing to deal
1812 with. 
1813
1814 <<process iface option line>>=
1815 <<convert [[post-up]] and [[pre-down]] aliases to [[up]] and [[down]]>>
1816 <<check for duplicate options>>
1817 <<add option>>
1818 @
1819
1820 <<convert [[post-up]] and [[pre-down]] aliases to [[up]] and [[down]]>>=
1821 if (strcmp(firstword, "post-up") == 0) {
1822         strcpy(firstword, "up");
1823 }
1824 if (strcmp(firstword, "pre-down") == 0) {
1825         strcpy(firstword, "down");
1826
1827 @
1828
1829 <<check for duplicate options>>=
1830 {
1831         int i;
1832
1833         if (strlen (rest) == 0) {
1834                 <<report empty option and die>>
1835         }
1836
1837         if (strcmp(firstword, "pre-up") != 0 
1838             && strcmp(firstword, "up") != 0
1839             && strcmp(firstword, "down") != 0
1840             && strcmp(firstword, "post-down") != 0)
1841         {
1842                 for (i = 0; i < currif->n_options; i++) {
1843                         if (strcmp(currif->option[i].name, firstword) == 0) {
1844                                 <<report duplicate option and die>>
1845                         }
1846                 }
1847         }
1848 }
1849
1850
1851 Adding an option is fairly straightforward: we simply construct
1852 a new variable and add it at the end of our array of variables,
1853 increasing the size of the array first if necessary.  Options with 
1854 empty values are rejected.
1855
1856 <<add option>>=
1857 if (currif->n_options >= currif->max_options) {
1858         <<increase max number of options>>
1859 }
1860
1861 currif->option[currif->n_options].name = strdup(firstword);
1862 currif->option[currif->n_options].value = strdup(rest);
1863
1864 if (!currif->option[currif->n_options].name) {
1865         <<report internal error and die>>
1866 }
1867
1868 if (!currif->option[currif->n_options].value) {
1869         <<report internal error and die>>
1870 }
1871
1872 currif->n_options++;    
1873 @
1874
1875 We'll increase the space for variables by a constant amount each time,
1876 rather than doubling or anything smart like that.
1877
1878 <<increase max number of options>>=
1879 {
1880         variable *opt;
1881         currif->max_options = currif->max_options + 10;
1882         opt = realloc(currif->option, sizeof(*opt) * currif->max_options);
1883         if (opt == NULL) {
1884                 <<report internal error and die>>
1885         }
1886         currif->option = opt;
1887 }
1888
1889
1890 \subsubsection{Auto and Allow Lines}
1891
1892 Processing the [[auto]] and [[allow-]] lines is pretty straightforward
1893 after the above, we just need to add each parameter to the list and
1894 check for duplicates. Since we're doing essentially the same thing twice,
1895 we'll break the common part out into a function.
1896
1897 <<process [[auto]] line>>=
1898 allowup_defn *auto_ups = get_allowup(&defn->allowups, "auto");
1899 if (!auto_ups) {
1900         <<report internal error and die>>
1901 }
1902 while((rest = next_word(rest, firstword, 80))) {
1903         if (!add_allow_up(filename, line, auto_ups, firstword))
1904                 return NULL;
1905 }
1906
1907 <<process [[allow-]] line>>=
1908 allowup_defn *allow_ups = get_allowup(&defn->allowups, firstword + 6);
1909 if (!allow_ups) {
1910         <<report internal error and die>>
1911 }
1912 while((rest = next_word(rest, firstword, 80))) {
1913         if (!add_allow_up(filename, line, allow_ups, firstword))
1914                 return NULL;
1915 }
1916
1917
1918 <<config function declarations>>=
1919 allowup_defn *get_allowup(allowup_defn **allowups, char *name);
1920
1921 <<config functions>>=
1922 allowup_defn *get_allowup(allowup_defn **allowups, char *name) {
1923         for (; *allowups; allowups = &(*allowups)->next) {
1924                 if (strcmp((*allowups)->when, name) == 0) break;
1925         }
1926         if (*allowups == NULL) {
1927                 *allowups = malloc(sizeof(allowup_defn));
1928                 if (*allowups == NULL) return NULL;
1929                 (*allowups)->when = strdup(name);
1930                 (*allowups)->next = NULL;
1931                 (*allowups)->max_interfaces = 0;
1932                 (*allowups)->n_interfaces = 0;
1933                 (*allowups)->interfaces = NULL;
1934         }
1935         return *allowups;
1936 }
1937 @
1938
1939 We'll want to export a little helper function to make finding the appropriate
1940 allowup easier too:
1941
1942 <<exported symbols>>=
1943 allowup_defn *find_allowup(interfaces_file *defn, char *name);
1944 @
1945
1946 <<config functions>>=
1947 allowup_defn *find_allowup(interfaces_file *defn, char *name) {
1948         allowup_defn *allowups = defn->allowups;
1949         for (; allowups; allowups = allowups->next) {
1950                 if (strcmp(allowups->when, name) == 0) break;
1951         }
1952         return allowups;
1953 }
1954 @
1955
1956 <<config function declarations>>=
1957 allowup_defn *add_allow_up(char *filename, int line,
1958          allowup_defn *allow_up, char *iface_name);
1959 @
1960
1961 <<config functions>>=
1962 allowup_defn *add_allow_up(char *filename, int line,
1963         allowup_defn *allow_up, char *iface_name)
1964 {
1965         <<check [[iface_name]] isn't already an [[allow_up]] interface or die>>
1966         <<add [[iface_name]] as an [[allow_up]] interface or die>>
1967         return allow_up;
1968 }
1969 @
1970
1971 <<check [[iface_name]] isn't already an [[allow_up]] interface or die>>=
1972 {
1973         int i;
1974
1975         for (i = 0; i < allow_up->n_interfaces; i++) {
1976                 if (strcmp(iface_name, allow_up->interfaces[i]) == 0) {
1977                         <<report [[iface_name]] as [[allow_up]] duplicate, die>>
1978                 }
1979         }
1980 }
1981 @
1982
1983 <<add [[iface_name]] as an [[allow_up]] interface or die>>=
1984 if (allow_up->n_interfaces == allow_up->max_interfaces) {
1985         char **tmp;
1986         allow_up->max_interfaces *= 2;
1987         allow_up->max_interfaces++;
1988         tmp = realloc(allow_up->interfaces, 
1989                 sizeof(*tmp) * allow_up->max_interfaces);
1990         if (tmp == NULL) {
1991                 <<report internal error and die>>
1992         }
1993         allow_up->interfaces = tmp;
1994 }
1995
1996 allow_up->interfaces[allow_up->n_interfaces] = strdup(iface_name);
1997 allow_up->n_interfaces++;
1998 @
1999
2000 \subsection{Error Handling}
2001
2002 We don't do anything too fancy about handling errors that occur, we
2003 just print out a hopefully helpful error message, and return from the
2004 function. \emph{We probably should also go to some effort to close files,
2005 and free memory, but well, you know. Maybe version $n+1$. --- aj}
2006
2007 <<report internal error and die>>=
2008 perror(filename);
2009 return NULL;
2010
2011
2012 <<report too few parameters for iface line and die>>=
2013 fprintf(stderr, "%s:%d: too few parameters for iface line\n", filename, line);
2014 return NULL;
2015 @
2016
2017 <<report too many parameters for iface line and die>>=
2018 fprintf(stderr, "%s:%d: too many parameters for iface line\n", filename, line);
2019 return NULL;
2020 @
2021
2022 <<report unknown address family and die>>=
2023 fprintf(stderr, "%s:%d: unknown address type\n", filename, line);
2024 return NULL;
2025 @
2026
2027 <<report unknown method and die>>=
2028 fprintf(stderr, "%s:%d: unknown method\n", filename, line);
2029 return NULL;
2030 @
2031
2032 <<report duplicate interface and die>>=
2033 fprintf(stderr, "%s:%d: duplicate interface\n", filename, line);
2034 return NULL;
2035 @
2036
2037 <<report [[iface_name]] as [[allow_up]] duplicate, die>>=
2038 fprintf(stderr, "%s:%d: interface %s declared allow-%s twice\n", 
2039         filename, line, iface_name, allow_up->when);
2040 return NULL;
2041 @
2042
2043 <<report duplicate option and die>>=
2044 fprintf(stderr, "%s:%d: duplicate option\n", filename, line);
2045 return NULL;
2046 @
2047
2048 <<report duplicate script in mapping and die>>=
2049 fprintf(stderr, "%s:%d: duplicate script in mapping\n", filename, line);
2050 return NULL;
2051
2052
2053 <<report bad option and die>>=
2054 fprintf(stderr, "%s:%d: misplaced option\n", filename, line);
2055 return NULL;
2056 @
2057
2058 <<report empty option and die>>=
2059 fprintf(stderr, "%s:%d: option with empty value\n", filename, line);
2060 return NULL;
2061
2062
2063 \section{Execution}
2064
2065 The [[execute]] module will be laid out in the standard manner, and
2066 will make use of the usual header files.
2067
2068 <<execute.c>>=
2069 <<execute headers>>
2070 <<execute global variables>>
2071 <<execute function declarations>>
2072 <<execute functions>>
2073
2074
2075 <<execute headers>>=
2076 #include <stdio.h>
2077 #include <ctype.h>
2078 #include <stdlib.h>
2079 #include <string.h>
2080 #include <assert.h>
2081
2082 #include "header.h"
2083 @
2084
2085 The key functions we export from here are all the functions that as a
2086 fairly direct result run some executable.
2087
2088 \begin{itemize}
2089         \item [[iface_up()]] and [[iface_down()]] which will actually
2090         configure or deconfigure an interface.
2091
2092         \item [[execute()]] which will take an interface definition and
2093         a command and fill in the details from the first into the
2094         second, and the execute the result. This is basically just a
2095         callback for the address family module.
2096
2097         \item [[run_mapping()]] which will run a mapping script and
2098         determine if a new logical interface should be selected.
2099 \end{itemize}
2100
2101 We'll discuss each of these in order.
2102
2103 \subsection{Interface Configuration and Deconfiguration}
2104
2105 Most of the complexity is involved in implementing the [[iface_up()]] and
2106 [[iface_down()]] functions. These are complicated enough that an explanatory
2107 diagram is probably useful:
2108
2109 \begin{center}
2110 \includegraphics[height=60mm]{execution}
2111 \end{center}
2112
2113 At a conceptual level, [[iface_up()]] and [[iface_down()]] have a
2114 reasonably straightforward job: they have to run one set of scripts,
2115 the configure or deconfigure the interface, then run another set of
2116 scripts.
2117
2118 This is complicated slightly in that they also have to handle the
2119 possibility that some of an interface's required arguments may be missing
2120 (in which case none of the commands should be attempted), and that some
2121 of the commands may fail (in which case none of the following commands
2122 should be attempted). We've already encoded most of the early-abort
2123 logic for the latter case into the address family definitions; so the way
2124 we'll handle the the former case is simply to call the address family's
2125 method [[up()]] or [[down()]] twice: once to ensure all the variables are
2126 appropriately filled out, and once to actually configure the interface.
2127
2128 \subsubsection{Command checking}
2129
2130 As such, we'll make use of two execution functions, each of which take
2131 one parameter, a shell command. We'll uninventively call these [[doit()]]
2132 and [[check()]]. They'll return 0 on failure, non-zero on success.
2133
2134 [[check()]] is thus fairly trivial:
2135
2136 <<execute function declarations>>=
2137 static int check(char *str);
2138 @
2139
2140 <<execute functions>>=
2141 static int check(char *str) {
2142         return str != NULL;
2143 }
2144
2145
2146 \subsubsection{Environment handling}
2147
2148 [[doit()]] is much more complicated, mainly by the fact that we
2149 don't simply want to just run the programs, but because we also want
2150 to setup a sanitized environment. In particular, we want to make the
2151 environment variables [[IFACE]], and [[MODE]] available (eg, [[eth0]] and
2152 [[start]] respectively), and we want to export all the given options as
2153 [[IF_OPTION]], with some sanitisation.
2154
2155 We'll do this just once per interface rather than once per command,
2156 and so we'll use a global variable to store our new environment, and a
2157 special function which will initialise it for us.
2158
2159 <<execute global variables>>=
2160 static char **environ = NULL;
2161
2162
2163 [[environ]] will be in the format used by the [[execle()]] function call,
2164 that is, a [[NULL]]-terminated array of strings of the form [[foo=bar]].
2165
2166 <<execute function declarations>>=
2167 static void set_environ(interface_defn *iface, char *mode, char *phase);
2168 @
2169
2170 Our function then will be:
2171
2172 <<execute functions>>=
2173 static void set_environ(interface_defn *iface, char *mode, char *phase) {
2174         <<variables local to set environ>>
2175         int i;
2176         const int n_env_entries = iface->n_options + 8;
2177
2178         <<initialise environ [[n_env_entries]]>>
2179
2180         for (i = 0; i < iface->n_options; i++) {
2181                 <<[[continue]] if option is a command>>
2182
2183                 <<add [[IF_]]option to environment>>
2184         }
2185
2186         <<add [[IFACE]] to environment>>
2187         <<add [[LOGICAL]] to environment>>
2188         <<add [[ADDRFAM]] to environment>>
2189         <<add [[METHOD]] to environment>>
2190
2191         <<add [[MODE]] to environment>>
2192         <<add [[PHASE]] to environment>>
2193         <<add [[VERBOSITY]] to environment>>
2194         <<add [[PATH]] to environment>>
2195 }
2196 @
2197
2198 Since we keep adding at the end, we'll make use of a pointer to keep track
2199 of where the end actually is, namely:
2200
2201 <<variables local to set environ>>=
2202 char **environend;
2203 @
2204
2205 Initialising thus becomes:
2206
2207 <<initialise environ [[n_env_entries]]>>=
2208 <<clear environ if necessary>>
2209 environ = malloc(sizeof(char*) * (n_env_entries + 1 /* for final NULL */));
2210 environend = environ; 
2211 *environend = NULL;
2212 @
2213
2214 <<clear environ if necessary>>=
2215 if (environ != NULL) {
2216         char **ppch;
2217         for (ppch = environ; *ppch; ppch++) {
2218                 free(*ppch);
2219                 *ppch = NULL;
2220         }
2221         free(environ);
2222         environ = NULL;
2223 }
2224 @
2225
2226 Our continue chunk is also fairly straight forward:
2227
2228 <<[[continue]] if option is a command>>=
2229 if (strcmp(iface->option[i].name, "pre-up") == 0
2230     || strcmp(iface->option[i].name, "up") == 0
2231     || strcmp(iface->option[i].name, "down") == 0
2232     || strcmp(iface->option[i].name, "post-down") == 0)
2233 {
2234         continue;
2235 }
2236 @
2237
2238 We'll make use of a small helper function for actually setting the
2239 environment. This function will handle [[malloc]]ing enough memory, and
2240 ensuring the environment variable name is reasonably sensible. It'll
2241 take three parameters: a [[printf]]-style format string presumed to
2242 contain two [[%s]]s, and the two parameters to that format string.
2243
2244 <<execute function declarations>>=
2245 static char *setlocalenv(char *format, char *name, char *value);
2246 @
2247
2248 We can then go ahead and fill in the environment.
2249
2250 <<add [[IF_]]option to environment>>=
2251 *(environend++) = setlocalenv("IF_%s=%s", iface->option[i].name,
2252                               iface->option[i].value);
2253 *environend = NULL;
2254 @
2255
2256 <<add [[IFACE]] to environment>>=
2257 *(environend++) = setlocalenv("%s=%s", "IFACE", iface->real_iface);
2258 *environend = NULL;
2259 @
2260
2261 <<add [[LOGICAL]] to environment>>=
2262 *(environend++) = setlocalenv("%s=%s", "LOGICAL", iface->logical_iface);
2263 *environend = NULL;
2264 @
2265
2266 <<add [[MODE]] to environment>>=
2267 *(environend++) = setlocalenv("%s=%s", "MODE", mode);
2268 *environend = NULL;
2269 @
2270
2271 <<add [[PHASE]] to environment>>=
2272 *(environend++) = setlocalenv("%s=%s", "PHASE", phase); 
2273 *environend = NULL;
2274 @
2275
2276 <<add [[PATH]] to environment>>=
2277 *(environend++) = setlocalenv("%s=%s", "PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
2278 *environend = NULL;
2279 @
2280
2281 <<add [[VERBOSITY]] to environment>>=
2282 *(environend++) = setlocalenv("%s=%s", "VERBOSITY", verbose ? "1" : "0");
2283 *environend = NULL;
2284 @
2285
2286 <<add [[ADDRFAM]] to environment>>=
2287 *(environend++) = setlocalenv("%s=%s", "ADDRFAM", iface->address_family->name);
2288 *environend = NULL;
2289 @
2290
2291 <<add [[METHOD]] to environment>>=
2292 *(environend++) = setlocalenv("%s=%s", "METHOD", iface->method->name);
2293 *environend = NULL;
2294 @
2295
2296 Our helper function then will then be something like:
2297
2298 <<execute functions>>=
2299 static char *setlocalenv(char *format, char *name, char *value) {
2300         char *result;
2301
2302         <<allocate memory for [[result]]>>
2303
2304         sprintf(result, format, name, value);
2305
2306         <<tidy [[result]]>>
2307
2308         return result;
2309 }
2310 @
2311
2312 Allocating the memory is fairly straightforward (although working out
2313 exactly how much memory involves a little guesswork, and assuming the
2314 caller passes in a reasonable [[format]]).
2315
2316 <<allocate memory for [[result]]>>=
2317 result = malloc(strlen(format)   /* -4 for the two %s's */
2318                 + strlen(name) 
2319                 + strlen(value) 
2320                 + 1);
2321 if (!result) {
2322         perror("malloc");
2323         exit(1);
2324 }
2325 @
2326
2327 And finally, tidying the result is a fairly simple matter of eliding all
2328 the characters we don't like, or translating them to ones we do like. We
2329 do like upper case letters, digits and underscores; and we're willing
2330 to translate hyphens and lower case letters. So here we go.
2331
2332 <<tidy [[result]]>>=
2333 {
2334         char *here, *there;
2335
2336         for(here = there = result; *there != '=' && *there; there++) {
2337                 if (*there == '-') *there = '_';
2338                 if (isalpha(*there)) *there = toupper(*there);
2339
2340                 if (isalnum(*there) || *there == '_') {
2341                         *here = *there;
2342                         here++;
2343                 }
2344         }
2345         memmove(here, there, strlen(there) + 1);
2346 }
2347 @
2348
2349 \subsubsection{Command Execution}
2350
2351 Our [[doit()]] function is then essentially a rewrite of the standard
2352 [[system()]] function call. The only additions are that we setup our
2353 child's environment as discussed previously, and we make use of two
2354 external globals, [[no_act]] and [[verbose]] and modify our behaviour
2355 based on those.
2356
2357 <<execute function declarations>>=
2358 static int doit(char *str);
2359 @
2360
2361 <<execute functions>>=
2362 static int doit(char *str) {
2363         assert(str);
2364
2365         if (verbose || no_act) {
2366                 fprintf(stderr, "%s\n", str);
2367         }
2368         if (!no_act) {
2369                 pid_t child;
2370                 int status;
2371
2372                 fflush(NULL);
2373                 switch(child = fork()) {
2374                     case -1: /* failure */
2375                         return 0;
2376                     case 0: /* child */
2377                         execle("/bin/sh", "/bin/sh", "-c", str, NULL, environ);
2378                         exit(127);
2379                     default: /* parent */
2380                         break;
2381                 }
2382                 waitpid(child, &status, 0);
2383                 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
2384                         return 0;
2385         }
2386         return 1;
2387 }
2388 @
2389
2390 \subsubsection{Executing a list of commands}
2391
2392 In addition to the above, we also need a function to cope with running
2393 all the [[pre-up]] commands and so forth.
2394
2395 <<exported symbols>>=
2396 int execute_all(interface_defn *ifd, execfn *exec, char *opt);
2397
2398
2399 All we need to do for this is to iterate through the options in the
2400 interface definition, and execute whichever ones are the right type,
2401 and call the [[run-parts]] command on the appropriate directory of
2402 scripts. That doesn't make for thrilling code.
2403
2404 This function will generally have [[doit]] passed in as the [[exec]]
2405 parameter.
2406
2407 <<execute functions>>=
2408 int execute_all(interface_defn *ifd, execfn *exec, char *opt) {
2409         int i;
2410         char buf[100];
2411         for (i = 0; i < ifd->n_options; i++) {
2412                 if (strcmp(ifd->option[i].name, opt) == 0) {
2413                         if (!(*exec)(ifd->option[i].value)) {
2414                                 return 0;
2415                         }
2416                 }
2417         }
2418
2419         snprintf(buf, sizeof(buf), "run-parts %s /etc/network/if-%s.d",
2420                 verbose ? "--verbose" : "", opt);
2421
2422         (*exec)(buf); 
2423
2424         return 1;
2425 }
2426
2427
2428 \subsubsection{[[iface_up()]] and [[iface_down()]]}
2429
2430 Our functions, then are:
2431
2432 <<exported symbols>>=
2433 int iface_up(interface_defn *iface);
2434 int iface_down(interface_defn *iface);
2435
2436
2437 <<execute functions>>=
2438 int iface_up(interface_defn *iface) {
2439         if (!iface->method->up(iface,check)) return -1;
2440
2441         set_environ(iface, "start", "pre-up");
2442         if (!execute_all(iface,doit,"pre-up")) return 0;
2443
2444         if (!iface->method->up(iface,doit)) return 0;
2445
2446         set_environ(iface, "start", "post-up");
2447         if (!execute_all(iface,doit,"up")) return 0;
2448
2449         return 1;
2450 }
2451
2452
2453 <<execute functions>>=
2454 int iface_down(interface_defn *iface) {
2455         if (!iface->method->down(iface,check)) return -1;
2456
2457         set_environ(iface, "stop", "pre-down");
2458         if (!execute_all(iface,doit,"down")) return 0;
2459
2460         if (!iface->method->down(iface,doit)) return 0;
2461
2462         set_environ(iface, "stop", "post-down");
2463         if (!execute_all(iface,doit,"post-down")) return 0;
2464
2465         return 1;
2466 }
2467
2468
2469 \subsection{Command Parsing}
2470
2471 All the above just leave one thing out: how the address family method's
2472 configuration function gets back to calling [[doit()]]. This function
2473 answers that question:
2474
2475 <<exported symbols>>=
2476 int execute(char *command, interface_defn *ifd, execfn *exec);
2477
2478
2479 At the somewhat abstract level, this is fairly trivial. The devil is
2480 in the details of the parsing, which makes up the rest of the module.
2481
2482 <<execute functions>>=
2483 int execute(char *command, interface_defn *ifd, execfn *exec) { 
2484         char *out;
2485         int ret;
2486
2487         out = parse(command, ifd);
2488         if (!out) { return 0; }
2489
2490         ret = (*exec)(out);
2491
2492         free(out);
2493         return ret;
2494 }
2495
2496
2497 We'll need a basic parser function, which we'll call [[parse()]], to
2498 make the appropriate substitutions into a command. It's probably worth
2499 a note as to exactly what substitutions may be made:
2500
2501 \begin{itemize}
2502
2503         \item Special characters can be escaped with a backslash. eg
2504         [[ls MoreThan80\%]].
2505
2506         \item Variables can be substituted by including their name
2507         delimeted by percents. eg [[ls %directory%]].
2508
2509         \item Optional components may be enclosed in double square
2510         brackets. Optional components will be included exactly when
2511         every variable referenced within exists. eg
2512         [[ls [[--color=%color%]]][[] %directory%]]. Optional components
2513         may be nested.
2514
2515 \end{itemize}
2516
2517 Most of the parsing is fairly straightforward -- basically, we keep an
2518 output buffer, and add things to it as we stroll through the input
2519 buffer: either the actual character we want, or whatever the value of
2520 the variable we're looking at is, or whatever. The only particularly
2521 complicated bit is how we deal with the optional sections, which will
2522 be explained when we get to them.
2523
2524 <<execute function declarations>>=
2525 static char *parse(char *command, interface_defn *ifd);
2526
2527
2528 <<execute functions>>=
2529 static char *parse(char *command, interface_defn *ifd) {
2530         <<variables local to parse>>
2531
2532         while(*command) {
2533                 switch(*command) {
2534                         <<handle a token>>
2535                 }
2536         }
2537
2538         <<deal with error conditions>>
2539
2540         <<return result>>
2541 }
2542 @
2543
2544 \subsubsection{Maintain output buffer}
2545
2546 So the first thing we need to do is actually write some code to deal
2547 with the output buffer, which will need to be dynamically resized and
2548 so on to take care of possibly long strings and what-not. It is the
2549 caller's responsibility to [[free()]] this buffer. We'll maintain two
2550 extra variables for convenience: who much memory we've allocated
2551 [[len]], and where the next character should be stuck [[pos]].
2552
2553 <<variables local to parse>>=
2554 char *result = NULL;
2555 size_t pos = 0, len = 0;
2556
2557
2558 This makes it pretty easy to return the result to the caller, too.
2559
2560 <<return result>>=
2561 return result;
2562 @
2563
2564 The main thing to be done to this buffer is to add characters or
2565 strings to it. To deal with this, we'll make use of an [[addstr()]]
2566 function that resizes the buffer as necessary, and appends a string to
2567 it. So we can deal with single characters, and substrings in general,
2568 we'll specify the string to be added as a pointer-length combination,
2569 rather than as a [[NUL]] terminated string.
2570
2571 <<execute function declarations>>=
2572 void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t strlen);
2573
2574
2575 <<execute functions>>=
2576 void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t strlen) {
2577         assert(*len >= *pos);
2578         assert(*len == 0 || (*buf)[*pos] == '\0');
2579
2580         if (*pos + strlen >= *len) {
2581                 char *newbuf;
2582                 newbuf = realloc(*buf, *len * 2 + strlen + 1);
2583                 if (!newbuf) {
2584                         perror("realloc");
2585                         exit(1); /* a little ugly */
2586                 }
2587                 *buf = newbuf;
2588                 *len = *len * 2 + strlen + 1;
2589         }
2590
2591         while (strlen-- >= 1) {
2592                 (*buf)[(*pos)++] = *str;
2593                 str++;
2594         }
2595         (*buf)[*pos] = '\0';
2596 }
2597
2598
2599 Given this, we can define our default behaviour for a character:
2600
2601 <<handle a token>>=
2602 default:
2603         addstr(&result, &len, &pos, command, 1);
2604         command++;
2605         break;
2606
2607
2608 \subsubsection{Escaped characters}
2609
2610 We can also deal pretty simply with escaped tokens. The only special
2611 circumstance is if the [[\]] is at the very end of string. We don't
2612 want buffer overflows afterall.
2613
2614 <<handle a token>>=
2615 case '\\':
2616         if (command[1]) {
2617                 addstr(&result, &len, &pos, command+1, 1);
2618                 command += 2;
2619         } else {
2620                 addstr(&result, &len, &pos, command, 1);
2621                 command++;
2622         }
2623         break;
2624
2625
2626 \subsubsection{Optional components}
2627
2628 Basically we keep track of each optional section we're in, whether
2629 we've been unable to fill in any variables, and where we started
2630 it. When we reach the end of an optional section, we check to see if
2631 we were unable to fill in any variables, and, if so, we discard any
2632 text we'd added within that block. This also allows us to neatly check
2633 for any errors trying to fill in variables that aren't in optional
2634 sections.
2635
2636 Basically what we'll do here is keep one stack to represent where the
2637 various thingos started, and another to represent whether any
2638 variables didn't exist. We'll use the bottom-most entry in the stack
2639 to represent the entire command, and thus keep track of whether or not
2640 we have to return an error because an undefined variable was used in a
2641 non-optional part of the command.
2642
2643 <<constant definitions>>=
2644 #define MAX_OPT_DEPTH 10
2645
2646
2647 <<variables local to parse>>=
2648 size_t old_pos[MAX_OPT_DEPTH] = {0};
2649 int okay[MAX_OPT_DEPTH] = {1};
2650 int opt_depth = 1;
2651
2652
2653 Given this, when we encounter a double open bracket, we need to just
2654 add the appropriate values to our stacks, and, similarly, when we
2655 encounter a double close bracket, we simply need to pop the stack, and
2656 see whether we need to move back or not, as well as taking care of an
2657 possible errors, naturally. \emph{We probably could actually give
2658 error messages here instead of just treating the brackets literally
2659 when they might cause problems. But there doesn't seem much point,
2660 really. --- aj}
2661
2662 <<handle a token>>=
2663 case '[':
2664         if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) {
2665                 old_pos[opt_depth] = pos;
2666                 okay[opt_depth] = 1;
2667                 opt_depth++;
2668                 command += 2;
2669         } else {
2670                 addstr(&result, &len, &pos, "[", 1);
2671                 command++;
2672         }
2673         break;
2674
2675
2676 <<handle a token>>=
2677 case ']':
2678         if (command[1] == ']' && opt_depth > 1) {
2679                 opt_depth--;
2680                 if (!okay[opt_depth]) {
2681                         pos = old_pos[opt_depth];
2682                         result[pos] = '\0';
2683                 }
2684                 command += 2;
2685         } else {
2686                 addstr(&result, &len, &pos, "]", 1);
2687                 command++;
2688         }
2689         break;
2690 @
2691
2692 Finally, at the end of the function, the stacks can be left in an
2693 unacceptable state --- either one of the optional blocks was never
2694 closed, or an undefined variable was used elsewhere. We'll note these
2695 circumstances by returning [[NULL]] and setting [[errno]].
2696
2697 <<execute headers>>=
2698 #include <errno.h>
2699 @
2700
2701 <<constant definitions>>=
2702 #define EUNBALBRACK 10001
2703 #define EUNDEFVAR   10002
2704
2705
2706 <<deal with error conditions>>=
2707 if (opt_depth > 1) {
2708         errno = EUNBALBRACK;
2709         free(result);
2710         return NULL;
2711 }
2712
2713 if (!okay[0]) {
2714         errno = EUNDEFVAR;
2715         free(result);
2716         return NULL;
2717 }
2718
2719
2720 \subsubsection{Variables}
2721
2722 Dealing with variables is comparatively fairly simple. We just need to
2723 find the next percent, and see if whatever's in-between is a variable,
2724 and, if so, get it's value.
2725
2726 <<constant definitions>>=
2727 #define MAX_VARNAME    32
2728 #define EUNBALPER   10000
2729
2730
2731 <<handle a token>>=
2732 case '%':
2733 {
2734         <<variables local to handle percent token>>
2735         char *varvalue;
2736
2737         <<determine variable name>>
2738
2739         <<get [[varvalue]]>>
2740
2741         if (varvalue) {
2742                 addstr(&result, &len, &pos, varvalue, strlen(varvalue));
2743         } else {
2744                 okay[opt_depth - 1] = 0;
2745         }
2746
2747         <<move to token after closing percent>>
2748
2749         break;
2750 }
2751
2752
2753 We don't do anything particularly clever dealing with the next percent
2754 --- just a pointer to the appropriate character.
2755
2756 <<variables local to handle percent token>>=
2757 char *nextpercent;
2758
2759
2760 <<determine variable name>>=
2761 command++;
2762 nextpercent = strchr(command, '%');
2763 if (!nextpercent) {
2764         errno = EUNBALPER;
2765         free(result);
2766         return NULL;
2767 }
2768
2769
2770 <<move to token after closing percent>>=
2771 command = nextpercent + 1;
2772 @
2773
2774 The slightly tricky thing we do here is use a [[strncmpz]] function,
2775 which allows us to check that a string represented by a [[char*]] and
2776 a length is the same as a [[NUL]] terminated string.
2777
2778 <<execute function declarations>>=
2779 int strncmpz(char *l, char *r, size_t llen);
2780
2781
2782 <<execute functions>>=
2783 int strncmpz(char *l, char *r, size_t llen) {
2784         int i = strncmp(l, r, llen);
2785         if (i == 0)
2786                 return -r[llen];
2787         else
2788                 return i;
2789 }
2790
2791
2792 Given the above, the implementation of the [[get_var()]] function to
2793 lookup the value of a variable, is reasonably straight forward.
2794
2795 <<execute function declarations>>=
2796 char *get_var(char *id, size_t idlen, interface_defn *ifd);
2797
2798
2799 <<execute functions>>=
2800 char *get_var(char *id, size_t idlen, interface_defn *ifd) {
2801         int i;
2802
2803         if (strncmpz(id, "iface", idlen) == 0) {
2804                 return ifd->real_iface;
2805         } else {
2806                 for (i = 0; i < ifd->n_options; i++) {
2807                         if (strncmpz(id, ifd->option[i].name, idlen) == 0) {
2808                                 return ifd->option[i].value;
2809                         }
2810                 }
2811         }
2812
2813         return NULL;
2814 }
2815
2816
2817 Which means we can finish of the chunk, thus:
2818
2819 <<get [[varvalue]]>>=
2820 varvalue = get_var(command, nextpercent - command, ifd);
2821
2822
2823 \subsection{Mapping Scripts}
2824
2825 Doing a mapping is moderately complicated, since we need to pass a
2826 fair bit of stuff to the script. The way we'll do this is via a
2827 mixture of command line arguments, and [[stdin]]: basically, we'll
2828 pass all the mapping variables from the interfaces file via [[stdin]],
2829 and anything else necessary will be a command line argument. The
2830 script will be expected to exit successfully with the appropriate
2831 logical interface as the first line of [[stdout]] if it made a match,
2832 or exit unsuccessfully (error code [[1]], eg) otherwise.
2833
2834 <<exported symbols>>=
2835 int run_mapping(char *physical, char *logical, int len, mapping_defn *map);
2836
2837
2838 <<execute functions>>=
2839 int run_mapping(char *physical, char *logical, int len, mapping_defn *map) {
2840         FILE *in, *out;
2841         int i, status;
2842         pid_t pid;
2843
2844         <<execute the mapping script>>
2845         <<send input to mapping script>>
2846         <<wait for mapping script to finish>>
2847         <<check output from mapping script>>
2848
2849         return 1;
2850 }
2851
2852
2853 The latter options here are fairly straightforward, given some Unix
2854 knowledge.
2855
2856 <<send input to mapping script>>=
2857 for (i = 0; i < map->n_mappings; i++) {
2858         fprintf(in, "%s\n", map->mapping[i]);
2859 }
2860 fclose(in);
2861
2862
2863 <<wait for mapping script to finish>>=
2864 waitpid(pid, &status, 0);
2865
2866
2867 <<check output from mapping script>>=
2868 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
2869         if (fgets(logical, len, out)) {
2870                 char *pch = logical + strlen(logical) - 1;
2871                 while (pch >= logical && isspace(*pch)) 
2872                         *(pch--) = '\0';
2873         }
2874 }
2875 fclose(out);    
2876
2877
2878 Slightly more complicated is setting up the child process and grabbing
2879 its [[stdin]] and [[stdout]]. Unfortunately we can't just use
2880 [[popen()]] for this, since it'll only allow us to go one way. So,
2881 instead we'll write our own [[popen()]]. It'll look like:
2882
2883 <<execute headers>>=
2884 #include <stdarg.h>
2885
2886
2887 <<execute function declarations>>=
2888 static int popen2(FILE **in, FILE **out, char *command, ...);
2889
2890
2891 The varargs component will be the arguments, as per [[execl()]], and
2892 the return value will be the [[PID]] if the call was successful, or 0
2893 otherwise.
2894
2895 As such, we will be able to execute the script thusly:
2896
2897 <<execute the mapping script>>=
2898 pid = popen2(&in, &out, map->script, physical, NULL);
2899 if (pid == 0) {
2900         return 0;
2901 }
2902
2903
2904 Writing [[popen2()]] is an exercise in Unix arcana.
2905
2906 <<execute headers>>=
2907 #include <unistd.h>
2908 #include <sys/wait.h>
2909
2910
2911 <<execute functions>>=
2912 static int popen2(FILE **in, FILE **out, char *command, ...) {
2913         va_list ap;
2914         char *argv[11] = {command};
2915         int argc;
2916         int infd[2], outfd[2];
2917         pid_t pid;
2918
2919         argc = 1;
2920         va_start(ap, command);
2921         while((argc < 10) && (argv[argc] = va_arg(ap, char*))) {
2922                 argc++;
2923         }
2924         argv[argc] = NULL; /* make sure */
2925         va_end(ap);
2926
2927         if (pipe(infd) != 0) return 0;
2928         if (pipe(outfd) != 0) {
2929                 close(infd[0]); close(infd[1]);
2930                 return 0;
2931         }
2932
2933         fflush(NULL);
2934         switch(pid = fork()) {
2935                 case -1: /* failure */
2936                         close(infd[0]); close(infd[1]);
2937                         close(outfd[0]); close(outfd[1]);
2938                         return 0;
2939                 case 0: /* child */
2940                         dup2(infd[0], 0);
2941                         dup2(outfd[1], 1);
2942                         close(infd[0]); close(infd[1]);
2943                         close(outfd[0]); close(outfd[1]);
2944                         execvp(command, argv);
2945                         exit(127);
2946                 default: /* parent */
2947                         *in = fdopen(infd[1], "w");
2948                         *out = fdopen(outfd[0], "r");
2949                         close(infd[0]); close(outfd[1]);
2950                         return pid;
2951         }
2952         /* unreached */
2953 }
2954 @
2955
2956 \section{The Driver}
2957
2958 The final C module we'll have is the one with the [[main()]]
2959 function. It's put together in a fairly straightforward way.
2960
2961 <<main.c>>=
2962 <<main headers>>
2963 <<main global variables>>
2964 <<main function declarations>>
2965 <<main functions>>
2966 <<main>>
2967
2968
2969 Equally, there's nothing particularly special about our headers.
2970
2971 <<main headers>>=
2972 #include <stdio.h>
2973 #include <stdlib.h>
2974 #include <string.h>
2975 #include <ctype.h>
2976 #include <errno.h>
2977 #include <assert.h>
2978
2979 #include "header.h"
2980 @
2981
2982 Now, after all the above modules, our main program doesn't have too
2983 much to do: it just has to interpret arguments and coordinate the
2984 intervening modules. Since we're being ``smart'', as well as parsing
2985 arguments, we'll decide whether the interface is going up or down
2986 depending on whether we were called as [[ifup]] or [[ifdown]].
2987
2988 <<main>>=
2989 int main(int argc, char **argv) {
2990         <<variables local to main>>
2991
2992         <<ensure environment is sane>>
2993
2994         <<parse command name or die>>
2995         <<parse arguments>>
2996
2997         <<read interfaces files or die>>
2998
2999         <<run commands for appropriate interfaces>>
3000
3001         return 0;
3002 }
3003 @
3004
3005 \subsection{Check the Environment}
3006
3007 In the earlier code we assume that we have stdin, stdout and stderr all
3008 available. We need to assure that, just in case:
3009
3010 <<main headers>>=
3011 #include <unistd.h>
3012 #include <fcntl.h>
3013 @
3014
3015 <<ensure environment is sane>>=
3016 {
3017         int i;
3018         for (i = 0; i <= 2; i++) {
3019                 if (fcntl(i, F_GETFD) == -1) {
3020                         if (errno == EBADF && open("/dev/null", 0) == -1) {
3021                                 fprintf(stderr,
3022                                         "%s: fd %d not available; aborting\n",
3023                                         argv[0], i);
3024                                 exit(2);
3025                         } else if (errno == EBADF) {
3026                                 errno = 0; /* no more problems */
3027                         } else {
3028                                 /* some other problem -- eeek */
3029                                 perror(argv[0]);
3030                                 exit(2);
3031                         }
3032                 }
3033         }
3034 }
3035 @
3036
3037 \subsection{Configuring or Deconfiguring?}
3038
3039 So the very first real thing we need to do is parse the command name. To
3040 do this, we'll obviously need to work out somewhere to store the result. A
3041 reasonable thing to do here is just to keep a function pointer about,
3042 which will point to one of the previously defined [[iface_up]] or
3043 [[iface_down]] functions, depending on which should be used on the
3044 specified interfaces.
3045
3046 <<variables local to main>>=
3047 int (*cmds)(interface_defn *) = NULL;
3048 @
3049
3050 So given this, we can just:
3051
3052 <<parse command name or die>>=
3053 {
3054         char *command;
3055
3056         <<set [[command]] to the base of the command name>>
3057         <<set [[cmds]] based on [[command]] or die>>
3058 }
3059 @
3060
3061 And fill out each component in the reasonably obvious manner of:
3062
3063 <<set [[command]] to the base of the command name>>=
3064 if ((command = strrchr(argv[0],'/'))) {
3065         command++; /* first char after / */
3066 } else {
3067         command = argv[0]; /* no /'s in argv[0] */
3068 }
3069 @
3070
3071 <<set [[cmds]] based on [[command]] or die>>=
3072 if (strcmp(command, "ifup")==0) {
3073         cmds = iface_up;
3074 } else if (strcmp(command, "ifdown")==0) {
3075         cmds = iface_down;
3076 } else {
3077         fprintf(stderr,"This command should be called as ifup or ifdown\n");
3078         exit(1);
3079 }
3080
3081
3082 In addition, since our later behaviour varies depending on whether we're
3083 bringing interfaces up or taking them down we'll define two chunks to assist
3084 with this, namely:
3085
3086 <<we're bringing interfaces up>>=
3087 (cmds == iface_up)
3088 @
3089
3090 <<we're taking interfaces down>>=
3091 (cmds == iface_down)
3092 @
3093
3094 The [[--allow]] option lets us limit the interfaces ifupdown will act on.
3095 It's implemented by having an [[allow_class]] that tells us which class
3096 of interfaces we're working with, and skipping interfaces that aren't
3097 in that class, like so:
3098
3099 <<we're limiting to [[--allow]]ed interfaces>>=
3100 (allow_class != NULL)
3101
3102 <<find [[iface]] in [[allow_class]] or [[continue]]>>=
3103 {
3104         int i;
3105         allowup_defn *allowup = find_allowup(defn, allow_class);
3106         if (allowup == NULL)
3107                 continue;
3108
3109         for (i = 0; i < allowup->n_interfaces; i++) {
3110                 if (strcmp(allowup->interfaces[i], iface) == 0)
3111                         break;
3112         }
3113         if (i >= allowup->n_interfaces)
3114                 continue;
3115 }
3116 @
3117
3118 Finally, the behaviour might vary depending on whether we are 
3119 excluding this interface or not. Notice that
3120 the exclude option can use a full interface name or substrings that
3121 match interfaces. A user could easily have unexpected behaviour
3122 if he uses a small string to do the match:
3123
3124 <<we're [[--exclude]]ing this interface>>=
3125 (excludeint != NULL && strstr(iface,excludeint) != NULL)
3126 @
3127
3128 \subsection{Argument Handling}
3129
3130 Okay, so next on our agenda is argument handling.
3131
3132 We'll do argument handling via the GNU [[getopt]] function, which
3133 means we have to include the appropriate header, and define a cute
3134 little structure to represent out long options:
3135
3136 <<main headers>>=
3137 #include <getopt.h>
3138 @
3139
3140 <<variables local to main>>=
3141 struct option long_opts[] = {
3142         {"help",        no_argument,       NULL, 'h'},
3143         {"version",     no_argument,       NULL, 'V'},
3144         {"verbose",     no_argument,       NULL, 'v'},
3145         {"all",         no_argument,       NULL, 'a'},
3146         {"allow",       required_argument, NULL,  3 },
3147         {"interfaces",  required_argument, NULL, 'i'},
3148         {"exclude",     required_argument, NULL, 'e'},
3149         {"no-act",      no_argument,       NULL, 'n'},
3150         {"no-mappings", no_argument,       NULL,  1 },
3151         {"force",       no_argument,       NULL,  2 },
3152         {0,0,0,0}
3153 };
3154
3155
3156 The usual way of dealing with options then is to have a variable to store
3157 the various things. The only special note here is that we need to export
3158 [[no_act]] and [[verbose]] to the [[execute]] module.
3159
3160 <<exported symbols>>=
3161 extern int no_act;
3162 extern int verbose;
3163 @
3164
3165 <<main global variables>>=
3166 int no_act = 0;
3167 int verbose = 0;
3168 @
3169
3170 <<variables local to main>>=
3171 int do_all = 0;
3172 int run_mappings = 1;
3173 int force = 0;
3174 char *allow_class = NULL;
3175 char *interfaces = "/etc/network/interfaces";
3176 char *statefile = "/etc/network/run/ifstate";
3177 char *excludeint = NULL ;
3178
3179
3180 We'll also have two helper functions to display usage information,
3181 like so:
3182
3183 <<main function declarations>>=
3184 static void usage(char *execname);
3185 static void help(char *execname);
3186 static void version(char *execname);
3187
3188
3189 <<main functions>>=
3190 static void usage(char *execname) {
3191         fprintf(stderr, "%s: Use --help for help\n", execname);
3192         exit(1);
3193 }
3194
3195
3196 <<main functions>>=
3197 static void version(char *execname) {
3198         printf("%s version " IFUPDOWN_VERSION "\n", execname);
3199         printf("Copyright (c) 1999-2005 Anthony Towns\n\n");
3200         printf(
3201
3202 "This program is free software; you can redistribute it and/or modify\n"
3203 "it under the terms of the GNU General Public License as published by\n"
3204 "the Free Software Foundation; either version 2 of the License, or (at\n"
3205 "your option) any later version.\n"
3206
3207         );
3208         exit(0);
3209 }
3210
3211
3212 <<main functions>>=
3213 static void help(char *execname) {
3214         printf("Usage: %s <options> <ifaces...>\n\n", execname);
3215         printf("Options:\n");
3216         printf("\t-h, --help\t\tthis help\n");
3217         printf("\t-V, --version\t\tcopyright and version information\n");
3218         printf("\t-a, --all\t\tde/configure all interfaces marked \"auto\"\n");
3219         printf("\t--allow CLASS\t\tignore non-\"allow-CLASS\" interfaces\n");
3220         printf("\t-i, --interfaces FILE\tuse FILE for interface definitions\n");
3221         printf("\t-n, --no-act\t\tprint out what would happen, but don't do it\n");
3222         printf("\t\t\t\t(note that this option doesn't disable mappings)\n");
3223         printf("\t-v, --verbose\t\tprint out what would happen before doing it\n");
3224         printf("\t--no-mappings\t\tdon't run any mappings\n");
3225         printf("\t--force\t\t\tforce de/configuration\n");
3226         exit(0);
3227 }
3228
3229
3230 Now, the meat of argument parsing is done with [[getopt()]] and a
3231 [[switch]], like so:
3232
3233 <<parse arguments>>=
3234 for(;;) {
3235         int c;
3236         c = getopt_long(argc, argv, "e:s:i:hVvna", long_opts, NULL);
3237         if (c == EOF) break;
3238
3239         switch(c) {
3240                 <<[[getopt]] possibilities>>
3241         }
3242 }
3243
3244 <<check unreasonable arguments>>
3245
3246
3247 Now, our [[getopt]] possibilities are basically each option, or something
3248 really bad. Actual interface names are automagically collected at the end
3249 by [[getopt()]].So first, the legitimate cases get handled:
3250
3251 <<[[getopt]] possibilities>>=
3252 case 'i':
3253         interfaces = strdup(optarg);
3254         break;
3255
3256 <<[[getopt]] possibilities>>=
3257 case 'v':
3258         verbose = 1;
3259         break;
3260
3261 <<[[getopt]] possibilities>>=
3262 case 'a':
3263         do_all = 1;
3264         break;
3265
3266 <<[[getopt]] possibilities>>=
3267 case 3:
3268         allow_class = strdup(optarg);
3269         break;
3270
3271 <<[[getopt]] possibilities>>=
3272 case 'n':
3273         no_act = 1;
3274         break;
3275
3276 <<[[getopt]] possibilities>>=
3277 case 1:
3278         run_mappings = 0;
3279         break;
3280
3281 <<[[getopt]] possibilities>>=
3282 case 2:
3283         force = 1;
3284         break;
3285 @
3286 <<[[getopt]] possibilities>>=
3287 case 'e':
3288         excludeint = strdup(optarg);
3289         break;
3290
3291
3292 And we also have a help option and a version option:
3293
3294 <<[[getopt]] possibilities>>=
3295 case 'h':
3296         help(argv[0]);
3297         break;
3298
3299 <<[[getopt]] possibilities>>=
3300 case 'V':
3301         version(argv[0]);
3302         break;
3303
3304
3305 And we also have the possibility that the user is just making up
3306 options:
3307
3308 <<[[getopt]] possibilities>>=
3309 default:
3310         usage(argv[0]);
3311         break;
3312 @
3313
3314 After all that there are still some things that can be a bit weird. We
3315 can be told either to act on all interfaces (except the noauto ones),
3316 or we can be told to act on specific interface. We won't accept been
3317 told to do both, and we won't accept not being told to do one or the
3318 other. We can test these two cases as follows:
3319
3320 <<check unreasonable arguments>>=
3321 if (argc - optind > 0 && do_all) {
3322         usage(argv[0]);
3323 }
3324
3325
3326 <<check unreasonable arguments>>=
3327 if (argc - optind == 0 && !do_all) {
3328         usage(argv[0]);
3329 }
3330
3331
3332 \subsection{Reading the Interfaces File}
3333
3334 Since this has all been covered in a previous section, this is pretty
3335 trivial.
3336
3337 <<variables local to main>>=
3338 interfaces_file *defn;
3339
3340
3341 <<read interfaces files or die>>=
3342 defn = read_interfaces(interfaces);
3343 if ( !defn ) {
3344         fprintf(stderr, "%s: couldn't read interfaces file \"%s\"\n",
3345                 argv[0], interfaces);
3346         exit(1);
3347 }
3348 @
3349
3350 \subsection{Execution}
3351
3352 A broad overview of what we'll actually be doing is as follows:
3353
3354 <<run commands for appropriate interfaces>>=
3355 <<lock 'n load ifupdown state>>
3356 <<determine target interfaces>>
3357 {
3358         int i;
3359         for (<<each target interface, [[i]]>>) {
3360                 char iface[80], liface[80];
3361
3362                 <<initialize [[iface]] to [[i]]th target interface>>
3363                 if (!force) {
3364                         <<check ifupdown state (possibly [[continue]])>>
3365                 }
3366
3367                 if (<<we're limiting to [[--allow]]ed interfaces>>) {
3368                         <<find [[iface]] in [[allow_class]] or [[continue]]>>
3369                 }
3370
3371                 if (<<we're [[--exclude]]ing this interface>>)  
3372                         continue;
3373
3374                 if (<<we're bringing interfaces up>> && run_mappings) {
3375                         <<run mappings>>
3376                 }
3377
3378                 <<bring interface up/down and update ifupdown state>>
3379                 <<commit ifupdown state>>
3380         }
3381 }
3382 <<close ifupdown state>>
3383 @
3384
3385 We'll leave determining the appropriate target interfaces and dealing
3386 with the state until a little later. That leaves us with covering running
3387 the mappings and bringing the interface up or taking it down.
3388
3389 Mappings are dealt with like so:
3390
3391 <<run mappings>>=
3392 {
3393         mapping_defn *currmap;
3394         for (currmap = defn->mappings; currmap; currmap = currmap->next) {
3395                 int i;
3396                 for (i = 0; i < currmap->n_matches; i++) {
3397                         <<[[continue]] unless mapping matches>>
3398                         <<run mapping>>
3399                         break;
3400                 }
3401         }
3402 }
3403 @
3404
3405 We check if mappings match by using shell globs, so we'll need a new header
3406 to take care of that.
3407
3408 <<main headers>>=
3409 #include <fnmatch.h>
3410
3411
3412 <<[[continue]] unless mapping matches>>=
3413 if (fnmatch(currmap->match[i], liface, 0) != 0)
3414         continue;
3415 @
3416
3417 Actually running a mapping is fairly straightforward, thanks to our
3418 previous handywork.
3419
3420 <<run mapping>>=
3421 if (verbose) {
3422         fprintf(stderr, "Running mapping script %s on %s\n",
3423                 currmap->script, liface);
3424 }
3425 run_mapping(iface, liface, sizeof(liface), currmap);
3426 @
3427
3428 Bringing an interface up or taking it down can be done thusly:
3429
3430 <<bring interface up/down and update ifupdown state>>=
3431 {
3432         interface_defn *currif;
3433         int okay = 0;
3434         int failed = 0; 
3435         for (currif = defn->ifaces; currif; currif = currif->next) {
3436                 if (strcmp(liface, currif->logical_iface) == 0) {
3437                         okay = 1;
3438
3439                         <<run commands for [[currif]]; set [[failed]] on error>>
3440
3441                         if (failed) break;
3442                         /* Otherwise keep going: this interface may have
3443                          * match with other address families */
3444                 }
3445         }
3446
3447         if (!okay && !force) {
3448                 fprintf(stderr, "Ignoring unknown interface %s=%s.\n", 
3449                         iface, liface);
3450         } else {
3451                 <<update ifupdown state>>
3452         }
3453 }
3454 @
3455
3456 <<run commands for [[currif]]; set [[failed]] on error>>=
3457 {
3458         currif->real_iface = iface;
3459
3460         if (verbose) {
3461                 fprintf(stderr, "Configuring interface %s=%s (%s)\n", 
3462                         iface, liface, currif->address_family->name);
3463         }
3464
3465         switch(cmds(currif)) {
3466             case -1:
3467                 printf("Don't seem to be have all the variables for %s/%s.\n", 
3468                         liface, currif->address_family->name);
3469                 failed = 1;
3470                 break;
3471             case 0:
3472                 failed = 1;
3473                 break;
3474                 /* not entirely successful */
3475             case 1:
3476                 failed = 0;
3477                 break;
3478                 /* successful */
3479             default:
3480                 printf("Internal error while configuring interface %s/%s (assuming it failed)\n", 
3481                         liface, currif->address_family->name);
3482                 failed = 1;
3483                 /* what happened here? */
3484         }
3485         currif->real_iface = NULL;
3486 }
3487
3488
3489 \subsection{Target Interfaces}
3490
3491 So, if we're going to actually do something, we should probably figure
3492 out exactly what we're going to do it to. So, we need to know the set
3493 of interfaces we're going to hax0r. This is just an array of interfaces,
3494 either [[physical_iface]] or [[physical_iface=logical_iface]].
3495
3496 <<variables local to main>>=
3497 int n_target_ifaces;
3498 char **target_iface;
3499
3500
3501 <<each target interface, [[i]]>>=
3502 i = 0; i < n_target_ifaces; i++
3503 @
3504
3505 We initialise this based on our command line arguments.
3506
3507 <<determine target interfaces>>=
3508 if (do_all) {
3509         if (<<we're bringing interfaces up>>) {
3510                 allowup_defn *autos = find_allowup(defn, "auto");
3511                 target_iface = autos ? autos->interfaces : NULL;
3512                 n_target_ifaces = autos ? autos->n_interfaces : 0;
3513         } else if (<<we're taking interfaces down>>) {
3514                 target_iface = state;
3515                 n_target_ifaces = n_state;
3516         } else {
3517                 assert(0);
3518         }       
3519 } else {
3520         target_iface = argv + optind;
3521         n_target_ifaces = argc - optind;
3522 }
3523
3524
3525 <<initialize [[iface]] to [[i]]th target interface>>=
3526 strncpy(iface, target_iface[i], sizeof(iface));
3527 iface[sizeof(iface)-1] = '\0';
3528
3529 {
3530         char *pch;
3531         if ((pch = strchr(iface, '='))) {
3532                 *pch = '\0';
3533                 strncpy(liface, pch+1, sizeof(liface));
3534                 liface[sizeof(liface)-1] = '\0';
3535         } else {
3536                 strncpy(liface, iface, sizeof(liface));
3537                 liface[sizeof(liface)-1] = '\0';
3538         }
3539 }
3540
3541
3542 \subsection{State}
3543
3544 Since it's generally not feasible to rerun a mapping script after an
3545 interface is configured (since a mapping script may well bring the
3546 interface down while it's investigating matters), we need to maintain a
3547 statefile between invocations to keep track of which physical interfaces
3548 were mapped to which logical ones. We ought to use 
3549 [[/var/run/ifupdown.state]] or something similar for this, but [[/var]]
3550 isn't guaranteed to be available until the network's up, so we'll use
3551 [[/etc/network/run/ifstate]] instead.
3552
3553 <<variables local to main>>=
3554 char **state = NULL; /* list of iface=liface */
3555 int n_state = 0;
3556 int max_state = 0;
3557
3558
3559 We'll also use two helper functions: one to lookup an interface, and one to
3560 add an interface.
3561
3562 <<main function declarations>>=
3563 static int lookfor_iface(char **ifaces, int n_ifaces, char *iface);
3564
3565
3566 <<main functions>>=
3567 static int lookfor_iface(char **ifaces, int n_ifaces, char *iface) {
3568         int i;
3569         for (i = 0; i < n_ifaces; i++) {
3570                 if (strncmp(iface, ifaces[i], strlen(iface)) == 0) {
3571                         if (ifaces[i][strlen(iface)] == '=') {
3572                                 return i;
3573                         }
3574                 }
3575         }
3576         return -1;
3577 }
3578
3579
3580 <<main function declarations>>=
3581 static void add_to_state(char ***ifaces, int *n_ifaces, int *max_ifaces, 
3582                          char *new_iface);
3583
3584
3585 <<main functions>>=
3586 static void add_to_state(char ***ifaces, int *n_ifaces, int *max_ifaces, 
3587                          char *new_iface)
3588 {
3589         assert(*max_ifaces >= *n_ifaces);
3590         if (*max_ifaces == *n_ifaces) {
3591                 *max_ifaces = (*max_ifaces * 2) + 1;
3592                 *ifaces = realloc(*ifaces, sizeof(**ifaces) * *max_ifaces);
3593                 if (*ifaces == NULL) {
3594                         perror("realloc");
3595                         exit(1);
3596                 }
3597         }
3598
3599         (*ifaces)[(*n_ifaces)++] = new_iface;
3600 }
3601
3602
3603 The state file is opened and locked, blocking parallel updates:
3604
3605 <<main function declarations>>=
3606 static int lock_fd (int fd);
3607
3608
3609 <<main functions>>=
3610 static int lock_fd (int fd) {
3611         struct flock lock;
3612
3613         lock.l_type = F_WRLCK;
3614         lock.l_whence = SEEK_SET;
3615         lock.l_start = 0;
3616         lock.l_len = 0;
3617
3618         if  (fcntl(fd, F_SETLKW, &lock) < 0) {
3619                 return -1;
3620         }
3621
3622         return 0;
3623 }
3624
3625
3626
3627 <<variables local to main>>=
3628 static FILE *state_fp = NULL;
3629 @
3630
3631 <<lock 'n load ifupdown state>>=
3632 {
3633         state_fp = fopen(statefile, no_act ? "r" : "a+");
3634         if (state_fp == NULL && !no_act) {
3635                 fprintf(stderr, 
3636                         "%s: failed to open statefile %s: %s\n",
3637                         argv[0], statefile, strerror(errno));
3638                 exit (1);
3639         }
3640
3641         if (state_fp != NULL) {
3642                 char buf[80];
3643                 char *p;
3644
3645                 if (!no_act) {
3646                         int flags;
3647
3648                         if ((flags = fcntl(fileno(state_fp), F_GETFD)) < 0
3649                             || fcntl(fileno(state_fp), F_SETFD, flags | FD_CLOEXEC) < 0) {
3650                                 fprintf(stderr, 
3651                                         "%s: failed to set FD_CLOEXEC on statefile %s: %s\n",
3652                                         argv[0], statefile, strerror(errno));
3653                                 exit(1);
3654                         }
3655
3656                         if (lock_fd (fileno(state_fp)) < 0) {
3657                                 fprintf(stderr, 
3658                                         "%s: failed to lock statefile %s: %s\n",
3659                                         argv[0], statefile, strerror(errno));
3660                                 exit(1);
3661                         }
3662
3663                 }
3664
3665                 rewind (state_fp);
3666                 while((p = fgets(buf, sizeof buf, state_fp)) != NULL) {
3667                         char *pch;
3668
3669                         pch = buf + strlen(buf) - 1;
3670                         while(pch > buf && isspace(*pch)) pch--;
3671                         *(pch+1) = '\0';
3672
3673                         pch = buf;
3674                         while(isspace(*pch)) pch++;
3675
3676                         add_to_state(&state, &n_state, &max_state, strdup(pch));
3677                 }
3678         }
3679 }
3680 @
3681
3682 <<close ifupdown state>>=
3683 if (state_fp != NULL) {
3684         fclose(state_fp);
3685         state_fp = NULL;
3686 }
3687 @
3688
3689
3690 <<commit ifupdown state>>=
3691 if (state_fp != NULL && !no_act) {
3692         int i;
3693
3694         if (ftruncate(fileno(state_fp), 0) < 0)
3695         {
3696                 fprintf(stderr, 
3697                         "%s: failed to truncate statefile %s: %s\n",
3698                         argv[0], statefile, strerror(errno));
3699                 exit(1);
3700         }
3701
3702         rewind(state_fp);
3703         for (i = 0; i < n_state; i++) {
3704                 fprintf(state_fp, "%s\n", state[i]);
3705         }
3706         fflush(state_fp);
3707 }
3708 @
3709
3710 This leaves our two useful chunks. The first checks to ensure what we're
3711 proposing to do is reasonable (ie, we're not downing an interface that's
3712 not up, or uping one that's not down).
3713
3714 <<check ifupdown state (possibly [[continue]])>>=
3715 {
3716         int already_up = lookfor_iface(state, n_state, iface);;
3717
3718         if (<<we're bringing interfaces up>>) {
3719                 if (already_up != -1) {
3720                         fprintf(stderr, 
3721                                 "%s: interface %s already configured\n",
3722                                 argv[0], iface);
3723                         continue;
3724                 }
3725         } else if (<<we're taking interfaces down>>) {
3726                 if (already_up == -1) {
3727                         fprintf(stderr, "%s: interface %s not configured\n",
3728                                 argv[0], iface);
3729                         continue;
3730                 }
3731                 strncpy(liface, strchr(state[already_up], '=') + 1, 80);
3732                 liface[79] = 0;
3733         } else {
3734                 assert(0);
3735         }
3736 }
3737
3738
3739 And finally, we also need to be able to update the state as we bring
3740 interfaces up and down.
3741
3742 <<update ifupdown state>>=
3743 {
3744         int already_up = lookfor_iface(state, n_state, iface);
3745
3746         if (<<we're bringing interfaces up>>) {
3747                 char *newiface = 
3748                         malloc(strlen(iface) + 1 + strlen(liface) + 1);
3749                 sprintf(newiface, "%s=%s", iface, liface);
3750
3751                 if (already_up == -1) {
3752                         if (failed == 1) {
3753                                 printf("Failed to bring up %s.\n", liface);
3754                         } else {
3755                                 add_to_state(&state, &n_state, &max_state, newiface);
3756                         }
3757                 } else {
3758                         free(state[already_up]);
3759                         state[already_up] = newiface;
3760                 }
3761         } else if (<<we're taking interfaces down>>) {
3762                 if (already_up != -1) {
3763                         state[already_up] = state[--n_state];
3764                 }
3765         } else {
3766                 assert(0);
3767         }
3768 }
3769
3770
3771 \appendix
3772
3773 \section{Linux Address Families}
3774
3775 <<archlinux.h>>=
3776 unsigned int mylinuxver();
3777 unsigned int mylinux(int,int,int);
3778 int execable(char *);
3779 @
3780
3781 <<archlinux.c>>=
3782 #include <stdio.h>
3783 #include <stdlib.h>
3784 #include <string.h>
3785 #include <unistd.h>
3786 #include <sys/utsname.h>
3787 #include <sys/stat.h>
3788
3789 #include "archlinux.h"
3790
3791 unsigned int mylinuxver() {
3792         static int maj = -1, rev, min;
3793
3794         if (maj == -1) {
3795                 struct utsname u;
3796                 char *pch;
3797                 uname(&u);
3798                 maj = atoi(u.release);
3799                 pch = strchr(u.release, '.');
3800                 rev = atoi(pch+1);
3801                 pch = strchr(pch+1, '.');
3802                 min = atoi(pch+1);
3803         }
3804
3805         return mylinux(maj,rev,min);
3806 }
3807
3808 unsigned int mylinux(int maj, int rev, int min) { 
3809         return min | rev << 10 | maj << 13;
3810 }
3811
3812 int execable(char *program) {
3813         struct stat buf;
3814
3815         if (0 == stat(program, &buf)) {
3816                 if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode)) return 1;
3817         }
3818         return 0;
3819 }
3820
3821
3822 \subsection{IPv4 Address Family}
3823
3824 <<address family declarations>>=
3825 extern address_family addr_inet;
3826
3827
3828 <<address family references>>=
3829 &addr_inet, 
3830
3831
3832 <<inet.defn>>=
3833 address_family inet
3834 architecture linux
3835
3836 <<inet methods>>
3837
3838
3839 <<inet methods>>=
3840 method loopback
3841   description
3842     This method may be used to define the IPv4 loopback interface.
3843
3844   up
3845     ifconfig %iface% 127.0.0.1 up
3846     route add -net 127.0.0.0       if ( mylinuxver() < mylinux(2,1,100) )
3847
3848   down
3849     ifconfig %iface% down
3850
3851
3852 <<inet methods>>=
3853 method static
3854   description
3855     This method may be used to define ethernet interfaces with statically
3856     allocated IPv4 addresses.
3857       
3858   options
3859     address address             -- Address (dotted quad) *required*
3860     netmask netmask             -- Netmask (dotted quad) *required*
3861     broadcast broadcast_address -- Broadcast address (dotted quad)
3862     network network_address     -- Network address (dotted quad) *required \
3863                                      for 2.0.x kernels*
3864     metric metric               -- Routing metric for default gateway (integer)
3865     gateway address             -- Default gateway (dotted quad)
3866     pointopoint address         -- Address of other end point (dotted quad). \
3867                                    Note the spelling of "point-to".
3868     media type                  -- Medium type, driver dependent
3869     hwaddress class address     -- Hardware Address. /class/ is one of \
3870                                      *ether*, *ax25*, *ARCnet* or *netrom*. \
3871                                      /address/ is dependent on the above \
3872                                      choice.
3873     mtu size                    -- MTU size
3874
3875   up
3876     [[ ifconfig %iface% hw %hwaddress%]]
3877     ifconfig %iface% %address% netmask %netmask% [[broadcast %broadcast%]] \
3878         [[pointopoint %pointopoint%]] [[media %media%]] [[mtu %mtu%]] \
3879         up
3880     route add -net %network%  \
3881         if ( mylinuxver() < mylinux(2,1,100) )
3882     [[ route add default gw %gateway% [[metric %metric%]] %iface% ]]
3883
3884   down
3885     [[ route del default gw %gateway% [[metric %metric%]] %iface% ]]
3886     ifconfig %iface% down
3887 @
3888
3889 <<inet methods>>=
3890 method manual
3891   description
3892     This method may be used to define interfaces for which no configuration
3893     is done by default.  Such interfaces can be configured manually by
3894     means of *up* and *down* commands or /etc/network/if-*.d scripts.
3895
3896   up
3897
3898   down
3899
3900
3901 <<inet methods>>=
3902 method dhcp
3903   description
3904     This method may be used to obtain an address via DHCP with any of
3905     the tools: dhclient, pump, udhcpc, dhcpcd.
3906     (They have been listed in their order of precedence.)
3907     If you have a complicated DHCP setup you should
3908     note that some of these clients use their own configuration files
3909     and do not obtain their configuration information via *ifup*.
3910
3911   options
3912     hostname hostname       -- Hostname to be requested (pump, dhcpcd, udhcpc)
3913     leasehours leastime     -- Preferred lease time in hours (pump)
3914     leasetime leasetime     -- Preferred lease time in seconds (dhcpcd)
3915     vendor vendor           -- Vendor class identifier (dhcpcd)
3916     client client_id        -- Client identifier (dhcpcd, udhcpc)
3917     hwaddress class address -- Hardware Address. /class/ is one of \
3918                                 *ether*, *ax25*, *ARCnet* or *netrom*. \
3919                                 /address/ is dependent on this choice.
3920
3921   up
3922     [[ifconfig %iface% hw %hwaddress%]]
3923     dhclient3 -pf /var/run/dhclient.%iface%.pid -lf /var/run/dhclient.%iface%.leases %iface% \
3924         if (execable("/sbin/dhclient3"))
3925     dhclient -e -pf /var/run/dhclient.%iface%.pid -lf /var/run/dhclient.%iface%.leases %iface% \
3926         elsif (execable("/sbin/dhclient"))
3927     pump -i %iface% [[-h %hostname%]] [[-l %leasehours%]] \
3928         elsif (execable("/sbin/pump") && mylinuxver() >= mylinux(2,1,100))
3929     udhcpc -n -p /var/run/udhcpc.%iface%.pid -i %iface% [[-H %hostname%]] \
3930            [[-c %clientid%]] \
3931         elsif (execable("/sbin/udhcpc") && mylinuxver() >= mylinux(2,2,0))
3932     dhcpcd [[-h %hostname%]] [[-i %vendor%]] [[-I %clientid%]] \
3933            [[-l %leasetime%]] %iface% \
3934         elsif (execable("/sbin/dhcpcd"))
3935
3936   down
3937     dhclient3 -r -pf /var/run/dhclient.%iface%.pid -lf /var/run/dhclient.%iface%.leases %iface% \
3938         if (execable("/sbin/dhclient3"))
3939     cat /var/run/dhclient.%iface%.pid | xargs -i kill -TERM {} \
3940         elsif (execable("/sbin/dhclient"))
3941     pump -i %iface% -r \
3942         elsif (execable("/sbin/pump") && mylinuxver() >= mylinux(2,1,100))
3943     cat /var/run/udhcpc.%iface%.pid | xargs -i kill -TERM {} \
3944         elsif (execable("/sbin/udhcpc"))
3945     dhcpcd -k %iface% \
3946         elsif (execable("/sbin/dhcpcd"))
3947
3948     ifconfig %iface% down
3949
3950
3951 <<inet methods>>=
3952 method bootp
3953   description
3954     This method may be used to obtain an address via bootp.
3955
3956   options
3957     bootfile file  -- Tell the server to use /file/ as the bootfile.
3958     server address -- Use the IP address /address/ to communicate with \
3959                       the server.
3960     hwaddr addr    -- Use /addr/ as the hardware address instead of \
3961                       whatever it really is.
3962
3963   up
3964     bootpc [[--bootfile %bootfile%]] --dev %iface% [[--server %server%]] \
3965            [[--hwaddr %hwaddr%]] --returniffail --serverbcast
3966
3967   down
3968     ifconfig down %iface%
3969
3970
3971 <<inet methods>>=
3972 method ppp
3973   description
3974     This method uses pon/poff to configure a PPP interface. See those
3975     commands for details.
3976   options
3977     provider name  -- Use /name/ as the provider (from /etc/ppp/peers).
3978   up
3979     pon [[%provider%]]
3980   down
3981     poff [[%provider%]]
3982
3983
3984 <<inet methods>>=
3985 method wvdial
3986   description
3987     This method uses wvdial to configure a PPP interface. See that command
3988     for more details.
3989   options
3990     provider name  -- Use /name/ as the provider (from /etc/ppp/peers).
3991   up
3992     /sbin/start-stop-daemon --start -x /usr/bin/wvdial \
3993                       -p /var/run/wvdial.%iface% -b -m -- [[ %provider% ]]
3994   down
3995     /sbin/start-stop-daemon --stop -x /usr/bin/wvdial \
3996                       -p /var/run/wvdial.%iface% -s 2
3997 @
3998
3999
4000
4001
4002 \subsection{IPv6 Address Family}
4003
4004 <<address family declarations>>=
4005 extern address_family addr_inet6;
4006
4007
4008 <<address family references>>=
4009 &addr_inet6,
4010
4011
4012 <<inet6.defn>>=
4013 address_family inet6
4014 architecture linux
4015
4016 method loopback
4017   description
4018     This method may be used to define the IPv6 loopback interface.
4019   up
4020     ifconfig %iface% add ::1
4021   down
4022     ifconfig %iface% del ::1
4023
4024 method static
4025   description
4026     This method may be used to define interfaces with statically assigned
4027     IPv6 addresses.
4028
4029   options
4030     address address        -- Address (colon delimited) *required*
4031     netmask mask           -- Netmask (number of bits, eg 64) *required*
4032     gateway address        -- Default gateway (colon delimited)
4033     media type             -- Medium type, driver dependent
4034     hwaddress class address -- Hardware Address. /class/ is one of \
4035                                  *ether*, *ax25*, *ARCnet* or *netrom*. \
4036                                  /address/ is dependent on this choice.
4037     mtu size               -- MTU size
4038   up
4039     ifconfig %iface% [[media %media%]] [[hw %hwaddress%]] [[mtu %mtu%]] up
4040     ifconfig %iface% add %address%/%netmask%
4041     [[ route -A inet6 add ::/0 gw %gateway% ]] 
4042
4043   down
4044     ifconfig %iface% down
4045
4046 method v4tunnel
4047   description
4048     This method may be used to setup an IPv6-over-IPv4 tunnel. It requires
4049     the *ip* command from the *iproute* package.
4050
4051   options
4052     address address       -- Address (colon delimited)
4053     netmask mask          -- Netmask (number of bits, eg 64) 
4054     endpoint address      -- Address of other tunnel endpoint (IPv4 \
4055                              dotted quad) *required*
4056     local address         -- Address of the local endpoint (IPv4 \
4057                              dotted quad)
4058     gateway address       -- Default gateway (colon delimited)
4059     ttl time              -- TTL setting
4060
4061   up
4062     ip tunnel add %iface% mode sit remote %endpoint% [[local %local%]] \
4063        [[ttl %ttl%]]
4064     ip link set %iface% up
4065     [[ ip addr add %address%/%netmask% dev %iface% ]]
4066     [[ ip route add %gateway% dev %iface% ]]
4067     [[ ip route add ::/0 via %gateway% dev %iface% ]]
4068
4069   down
4070     ip tunnel del %iface%
4071
4072
4073 \subsection{IPX Address Family}
4074
4075 <<address family declarations>>=
4076 extern address_family addr_ipx;
4077
4078
4079 <<address family references>>=
4080 &addr_ipx,
4081
4082
4083 <<ipx.defn>>=
4084 address_family ipx
4085 architecture linux
4086
4087 method static
4088   description
4089     This method may be used to setup an IPX interface.  It requires the
4090     /ipx_interface/ command.
4091
4092   options
4093     frame type             -- /type/ of ethernet frames to use (e.g. *802.2*)
4094     netnum id              -- Network number
4095
4096   up
4097     ipx_interface add %iface% %frame% %netnum%
4098
4099   down
4100     ipx_interface del %iface% %frame%
4101
4102 method dynamic
4103   description
4104     This method may be used to setup an IPX interface dynamically.
4105
4106   options
4107     frame type             -- /type/ of ethernet frames to use (e.g. *802.2*)
4108
4109   up
4110     ipx_interface add %iface% %frame%
4111
4112   down
4113     ipx_interface del %iface% %frame%
4114
4115
4116 \begin{flushleft}
4117 \bibliography{biblio}
4118 \bibliographystyle{unsrt}
4119 \end{flushleft}
4120
4121 \end{document}