diff options
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/getty/Makefile | 10 | ||||
-rw-r--r-- | libexec/getty/extern.h | 56 | ||||
-rw-r--r-- | libexec/getty/getty.8 | 127 | ||||
-rw-r--r-- | libexec/getty/gettytab.5 | 324 | ||||
-rw-r--r-- | libexec/getty/gettytab.h | 145 | ||||
-rw-r--r-- | libexec/getty/init.c | 121 | ||||
-rw-r--r-- | libexec/getty/main.c | 549 | ||||
-rw-r--r-- | libexec/getty/pathnames.h | 39 | ||||
-rw-r--r-- | libexec/getty/subr.c | 531 | ||||
-rw-r--r-- | libexec/getty/ttys.5 | 139 | ||||
-rw-r--r-- | libexec/rbootd/Makefile | 11 | ||||
-rw-r--r-- | libexec/rbootd/bpf.c | 422 | ||||
-rw-r--r-- | libexec/rbootd/conf.c | 90 | ||||
-rw-r--r-- | libexec/rbootd/defs.h | 185 | ||||
-rw-r--r-- | libexec/rbootd/parseconf.c | 359 | ||||
-rw-r--r-- | libexec/rbootd/pathnames.h | 51 | ||||
-rw-r--r-- | libexec/rbootd/rbootd.8 | 156 | ||||
-rw-r--r-- | libexec/rbootd/rbootd.c | 508 | ||||
-rw-r--r-- | libexec/rbootd/rmp.h | 95 | ||||
-rw-r--r-- | libexec/rbootd/rmp_var.h | 244 | ||||
-rw-r--r-- | libexec/rbootd/rmpproto.c | 593 | ||||
-rw-r--r-- | libexec/rbootd/utils.c | 557 |
22 files changed, 5312 insertions, 0 deletions
diff --git a/libexec/getty/Makefile b/libexec/getty/Makefile new file mode 100644 index 0000000..7f2eabe --- /dev/null +++ b/libexec/getty/Makefile @@ -0,0 +1,10 @@ +# @(#)Makefile 8.1 (Berkeley) 6/4/93 + +PROG= getty +SRCS= main.c init.c subr.c ttydefaults.c +DPADD= ${LIBUTIL} +LDADD= -lutil +MAN5= gettytab.0 ttys.0 +MAN8= getty.0 + +.include <bsd.prog.mk> diff --git a/libexec/getty/extern.h b/libexec/getty/extern.h new file mode 100644 index 0000000..644f93f --- /dev/null +++ b/libexec/getty/extern.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/4/93 + */ + +struct delayval; + +int adelay __P((int, struct delayval *)); +char *autobaud __P((void)); +int delaybits __P((void)); +void edithost __P((char *)); +void gendefaults __P((void)); +int getent __P((char *, char *)); +int getflag __P((char *)); +long getnum __P((char *)); +char *getstr __P((char *, char **)); +void gettable __P((char *, char *)); +void makeenv __P((char *[])); +char *portselector __P((void)); +void set_ttydefaults __P((int)); +void setchars __P((void)); +void setdefaults __P((void)); +long setflags __P((int)); +int speed __P((int)); + +int login_tty __P((int)); /* From libutil. */ diff --git a/libexec/getty/getty.8 b/libexec/getty/getty.8 new file mode 100644 index 0000000..ffd5060 --- /dev/null +++ b/libexec/getty/getty.8 @@ -0,0 +1,127 @@ +.\" Copyright (c) 1980, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)getty.8 8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt GETTY 8 +.Os BSD 4 +.Sh NAME +.Nm getty +.Nd set terminal mode +.Sh SYNOPSIS +.Nm getty +.Oo +.Ar type +.Op Ar tty +.Oc +.Sh DESCRIPTION +The +.Nm getty +program +is called by +.Xr init 8 +to open and initialize the tty line, read a login name, and invoke +.Xr login 1 . +.Pp +The argument +.Ar tty +is the special device file in +.Pa /dev +to open for the terminal (for example, ``ttyh0''). +If there is no argument or the argument is +.Ql Fl , +the tty line is assumed to be open as file descriptor 0. +.Pp +The +.Ar type +argument can be used to make +.Nm getty +treat the terminal line specially. +This argument is used as an index into the +.Nm gettytab 5 +database, to determine the characteristics of the line. +If there is no argument, or there is no such table, the +.Em default +table is used. +If there is no +.Pa /etc/gettytab +a set of system defaults is used. +If indicated by the table located, +.Nm getty +will clear the terminal screen, +print a banner heading, +and prompt for a login name. +Usually either the banner or the login prompt will include +the system hostname. +.Pp +Most of the default actions of +.Nm getty +can be circumvented, or modified, by a suitable +.Nm gettytab +table. +.Pp +The +.Nm getty +program +can be set to timeout after some interval, +which will cause dial up lines to hang up +if the login name is not entered reasonably quickly. +.Sh DIAGNOSTICS +.Bl -diag +.It "ttyxx: No such device or address." +.It "ttyxx: No such file or address." +A terminal which is turned +on in the +.Xr ttys +file cannot be opened, likely because the requisite +lines are either not configured into the system, the associated device +was not attached during boot-time system configuration, +or the special file in +.Pa /dev +does not exist. +.El +.Sh FILES +.Bl -tag -width /etc/gettytab -compact +.It Pa /etc/gettytab +.El +.Sh SEE ALSO +.Xr gettytab 5 , +.Xr init 8 , +.Xr login 1 , +.Xr ioctl 2 , +.Xr tty 4 , +.Xr ttys 5 +.Sh HISTORY +A +.Nm getty +program appeared in +.At v6 . diff --git a/libexec/getty/gettytab.5 b/libexec/getty/gettytab.5 new file mode 100644 index 0000000..a9bbd53 --- /dev/null +++ b/libexec/getty/gettytab.5 @@ -0,0 +1,324 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)gettytab.5 8.4 (Berkeley) 4/19/94 +.\" +.Dd April 19, 1994 +.Dt GETTYTAB 5 +.Os BSD 4.2 +.Sh NAME +.Nm gettytab +.Nd terminal configuration data base +.Sh SYNOPSIS +.Nm gettytab +.Sh DESCRIPTION +The +.Nm gettytab +file +is a simplified version of the +.Xr termcap 5 +data base +used to describe terminal lines. +The initial terminal login process +.Xr getty 8 +accesses the +.Nm gettytab +file each time it starts, allowing simpler +reconfiguration of terminal characteristics. +Each entry in the data base +is used to describe one class of terminals. +.Pp +There is a default terminal class, +.Em default , +that is used to set global defaults for all other classes. +(That is, the +.Em default +entry is read, then the entry for the class required +is used to override particular settings.) +.Sh CAPABILITIES +Refer to +.Xr termcap 5 +for a description of the file layout. +The +.Em default +column below lists defaults obtained if there is +no entry in the table obtained, nor one in the special +.Em default +table. +.Bl -column Namexx /usr/bin/login Default +.It Sy Name Type Default Description +.It "ap bool false terminal uses any parity" +.It "bd num 0 backspace delay" +.It "bk str 0377 alternate end of line character (input break)" +.It "cb bool false use crt backspace mode" +.It "cd num 0 carriage-return delay" +.It "ce bool false use crt erase algorithm" +.It "ck bool false use crt kill algorithm" +.It "cl str" Ta Dv NULL Ta +.No "screen clear sequence" +.It "co bool false console - add" +.Ql \en +after login prompt +.It "ds str" Ta So Li ^Y Sc Ta +.No "delayed suspend character" +.It "dx bool false set" +.Dv DECCTLQ +.It "ec bool false leave echo" +.Tn OFF +.It "ep bool false terminal uses even parity" +.It "er str" Ta So Li ^? Sc Ta +.No "erase character" +.It "et str" Ta So Li ^D Sc Ta +.No "end of text" +.Pq Dv EOF +character +.It "ev str" Ta Dv NULL Ta +.No "initial environment" +.It "f0 num unused tty mode flags to write messages" +.It "f1 num unused tty mode flags to read login name" +.It "f2 num unused tty mode flags to leave terminal as" +.It "fd num 0 form-feed (vertical motion) delay" +.It "fl str" Ta So Li ^O Sc Ta +.No "output flush character" +.It "hc bool false do" +.Tn NOT +hangup line on last close +.It "he str" Ta Dv NULL Ta +.No "hostname editing string" +.It "hn str hostname hostname" +.It "ht bool false terminal has real tabs" +.It "ig bool false ignore garbage characters in login name" +.It "im str" Ta Dv NULL Ta +.No "initial (banner) message" +.It "in str" Ta So Li ^C Sc Ta +.No "interrupt character" +.It "is num unused input speed" +.It "kl str" Ta So Li ^U Sc Ta +.No "kill character" +.It "lc bool false terminal has lower case" +.It "lm str login: login prompt" +.It "ln str" Ta So Li ^V Sc Ta +.No "``literal next'' character" +.It "lo str" Ta Pa /usr/bin/login Ta +.No "program to exec when name obtained" +.It "nd num 0 newline (line-feed) delay" +.It "nl bool false terminal has (or might have) a newline character" +.It "np bool false terminal uses no parity (i.e. 8-bit characters)" +.It "nx str default next table (for auto speed selection)" +.It "op bool false terminal uses odd parity" +.It "os num unused output speed" +.It "pc str" Ta So Li \e0 Sc Ta +.No "pad character" +.It "pe bool false use printer (hard copy) erase algorithm" +.It "pf num 0 delay" +between first prompt and following flush (seconds) +.It "ps bool false line connected to a" +.Tn MICOM +port selector +.It "qu str" Ta So Li \&^\e Sc Ta +.No "quit character" +.It "rp str" Ta So Li ^R Sc Ta +.No "line retype character" +.It "rw bool false do" +.Tn NOT +use raw for input, use cbreak +.It "sp num unused line speed (input and output)" +.It "su str" Ta So Li ^Z Sc Ta +.No "suspend character" +.It "tc str none table continuation" +.It "to num 0 timeout (seconds)" +.It "tt str" Ta Dv NULL Ta +.No "terminal type (for environment)" +.It "ub bool false do unbuffered output (of prompts etc)" +.It "uc bool false terminal is known upper case only" +.It "we str" Ta So Li ^W Sc Ta +.No "word erase character" +.It "xc bool false do +.Tn NOT +echo control chars as +.Ql ^X +.It "xf str" Ta So Li ^S Sc Ta Dv XOFF +(stop output) character +.It "xn str" Ta So Li ^Q Sc Ta Dv XON +(start output) character +.El +.Pp +If no line speed is specified, speed will not be altered +from that which prevails when getty is entered. +Specifying an input or output speed will override +line speed for stated direction only. +.Pp +Terminal modes to be used for the output of the message, +for input of the login name, +and to leave the terminal set as upon completion, +are derived from the boolean flags specified. +If the derivation should prove inadequate, +any (or all) of these three may be overridden +with one of the +.Em \&f0 , +.Em \&f1 , +or +.Em \&f2 +numeric specifications, which can be used to specify +(usually in octal, with a leading '0') +the exact values of the flags. +Local (new tty) flags are set in the top 16 bits +of this (32 bit) value. +.Pp +Should +.Xr getty +receive a null character +(presumed to indicate a line break) +it will restart using the table indicated by the +.Em nx +entry. If there is none, it will re-use its original table. +.Pp +Delays are specified in milliseconds, the nearest possible +delay available in the tty driver will be used. +Should greater certainty be desired, delays +with values 0, 1, 2, and 3 are interpreted as +choosing that particular delay algorithm from the driver. +.Pp +The +.Em \&cl +screen clear string may be preceded by a (decimal) number +of milliseconds of delay required (a la termcap). +This delay is simulated by repeated use of the pad character +.Em \&pc . +.Pp +The initial message, and login message, +.Em \&im +and +.Em \&lm +may include the character sequence +.Em \&%h +or +.Em \&%t +to obtain +the hostname or tty name respectively. +.Pf ( Em %% +obtains a single '%' character.) +The hostname is normally obtained from the system, +but may be set by the +.Em \&hn +table entry. +In either case it may be edited with +.Em \&he . +The +.Em \&he +string is a sequence of characters, each character that +is neither '@' nor '#' is copied into the final hostname. +A '@' in the +.Em \&he +string, causes one character from the real hostname to +be copied to the final hostname. +A '#' in the +.Em \&he +string, causes the next character of the real hostname +to be skipped. +Surplus '@' and '#' characters are ignored. +.Pp +When getty execs the login process, given +in the +.Em \&lo +string (usually +.Dq Pa /usr/bin/login ) , +it will have set +the environment to include the terminal type, as indicated +by the +.Em \&tt +string (if it exists). +The +.Em \&ev +string, can be used to enter additional data into +the environment. +It is a list of comma separated strings, each of which +will presumably be of the form +.Em name=value . +.Pp +If a non-zero timeout is specified, with +.Em \&to , +then getty will exit within the indicated +number of seconds, either having +received a login name and passed control +to +.Xr login , +or having received an alarm signal, and exited. +This may be useful to hangup dial in lines. +.Pp +Output from +.Xr getty +is even parity unless +.Em \&op +is specified. +The +.Em \&op +string +may be specified with +.Em \&ap +to allow any parity on input, but generate odd parity output. +Note: this only applies while getty is being run, +terminal driver limitations prevent a more complete +implementation. +.Xr Getty +does not check parity of input characters in +.Dv RAW +mode. +.Sh SEE ALSO +.Xr login 1 , +.Xr termcap 5 , +.Xr getty 8 . +.Sh BUGS +The special characters (erase, kill, etc.) are reset to system defaults +by +.Xr login 1 . +In +.Em all +cases, '#' or '^H' typed in a login name will be treated as +an erase character, and '@' will be treated as a kill character. +.Pp +The delay stuff is a real crock. +Apart form its general lack of flexibility, some +of the delay algorithms are not implemented. +The terminal driver should support sane delay settings. +.Pp +The +.Em \&he +capability is stupid. +.Pp +The +.Xr termcap +format is horrid, something more rational should +have been chosen. +.Sh HISTORY +The +.Nm gettytab +file format appeared in 4.2BSD. diff --git a/libexec/getty/gettytab.h b/libexec/getty/gettytab.h new file mode 100644 index 0000000..fb2b14f --- /dev/null +++ b/libexec/getty/gettytab.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)gettytab.h 8.2 (Berkeley) 3/30/94 + */ + +/* + * Getty description definitions. + */ +struct gettystrs { + char *field; /* name to lookup in gettytab */ + char *defalt; /* value we find by looking in defaults */ + char *value; /* value that we find there */ +}; + +struct gettynums { + char *field; /* name to lookup */ + long defalt; /* number we find in defaults */ + long value; /* number we find there */ + int set; /* we actually got this one */ +}; + +struct gettyflags { + char *field; /* name to lookup */ + char invrt; /* name existing in gettytab --> false */ + char defalt; /* true/false in defaults */ + char value; /* true/false flag */ + char set; /* we found it */ +}; + +/* + * String values. + */ +#define NX gettystrs[0].value +#define CL gettystrs[1].value +#define IM gettystrs[2].value +#define LM gettystrs[3].value +#define ER gettystrs[4].value +#define KL gettystrs[5].value +#define ET gettystrs[6].value +#define PC gettystrs[7].value +#define TT gettystrs[8].value +#define EV gettystrs[9].value +#define LO gettystrs[10].value +#define HN gettystrs[11].value +#define HE gettystrs[12].value +#define IN gettystrs[13].value +#define QU gettystrs[14].value +#define XN gettystrs[15].value +#define XF gettystrs[16].value +#define BK gettystrs[17].value +#define SU gettystrs[18].value +#define DS gettystrs[19].value +#define RP gettystrs[20].value +#define FL gettystrs[21].value +#define WE gettystrs[22].value +#define LN gettystrs[23].value + +/* + * Numeric definitions. + */ +#define IS gettynums[0].value +#define OS gettynums[1].value +#define SP gettynums[2].value +#define ND gettynums[3].value +#define CD gettynums[4].value +#define TD gettynums[5].value +#define FD gettynums[6].value +#define BD gettynums[7].value +#define TO gettynums[8].value +#define F0 gettynums[9].value +#define F0set gettynums[9].set +#define F1 gettynums[10].value +#define F1set gettynums[10].set +#define F2 gettynums[11].value +#define F2set gettynums[11].set +#define PF gettynums[12].value + +/* + * Boolean values. + */ +#define HT gettyflags[0].value +#define NL gettyflags[1].value +#define EP gettyflags[2].value +#define EPset gettyflags[2].set +#define OP gettyflags[3].value +#define OPset gettyflags[3].set +#define AP gettyflags[4].value +#define APset gettyflags[4].set +#define EC gettyflags[5].value +#define CO gettyflags[6].value +#define CB gettyflags[7].value +#define CK gettyflags[8].value +#define CE gettyflags[9].value +#define PE gettyflags[10].value +#define RW gettyflags[11].value +#define XC gettyflags[12].value +#define LC gettyflags[13].value +#define UC gettyflags[14].value +#define IG gettyflags[15].value +#define PS gettyflags[16].value +#define HC gettyflags[17].value +#define UB gettyflags[18].value +#define AB gettyflags[19].value +#define DX gettyflags[20].value +#define NP gettyflags[21].value + +int getent __P((char *, char *)); +long getnum __P((char *)); +int getflag __P((char *)); +char *getstr __P((char *, char **)); + +extern struct gettyflags gettyflags[]; +extern struct gettynums gettynums[]; +extern struct gettystrs gettystrs[]; +extern int hopcount; diff --git a/libexec/getty/init.c b/libexec/getty/init.c new file mode 100644 index 0000000..835acd7 --- /dev/null +++ b/libexec/getty/init.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * Getty table initializations. + * + * Melbourne getty. + */ +#include <sgtty.h> +#include "gettytab.h" +#include "pathnames.h" + +extern struct sgttyb tmode; +extern struct tchars tc; +extern struct ltchars ltc; +extern char hostname[]; + +struct gettystrs gettystrs[] = { + { "nx" }, /* next table */ + { "cl" }, /* screen clear characters */ + { "im" }, /* initial message */ + { "lm", "login: " }, /* login message */ + { "er", &tmode.sg_erase }, /* erase character */ + { "kl", &tmode.sg_kill }, /* kill character */ + { "et", &tc.t_eofc }, /* eof chatacter (eot) */ + { "pc", "" }, /* pad character */ + { "tt" }, /* terminal type */ + { "ev" }, /* enviroment */ + { "lo", _PATH_LOGIN }, /* login program */ + { "hn", hostname }, /* host name */ + { "he" }, /* host name edit */ + { "in", &tc.t_intrc }, /* interrupt char */ + { "qu", &tc.t_quitc }, /* quit char */ + { "xn", &tc.t_startc }, /* XON (start) char */ + { "xf", &tc.t_stopc }, /* XOFF (stop) char */ + { "bk", &tc.t_brkc }, /* brk char (alt \n) */ + { "su", <c.t_suspc }, /* suspend char */ + { "ds", <c.t_dsuspc }, /* delayed suspend */ + { "rp", <c.t_rprntc }, /* reprint char */ + { "fl", <c.t_flushc }, /* flush output */ + { "we", <c.t_werasc }, /* word erase */ + { "ln", <c.t_lnextc }, /* literal next */ + { 0 } +}; + +struct gettynums gettynums[] = { + { "is" }, /* input speed */ + { "os" }, /* output speed */ + { "sp" }, /* both speeds */ + { "nd" }, /* newline delay */ + { "cd" }, /* carriage-return delay */ + { "td" }, /* tab delay */ + { "fd" }, /* form-feed delay */ + { "bd" }, /* backspace delay */ + { "to" }, /* timeout */ + { "f0" }, /* output flags */ + { "f1" }, /* input flags */ + { "f2" }, /* user mode flags */ + { "pf" }, /* delay before flush at 1st prompt */ + { 0 } +}; + +struct gettyflags gettyflags[] = { + { "ht", 0 }, /* has tabs */ + { "nl", 1 }, /* has newline char */ + { "ep", 0 }, /* even parity */ + { "op", 0 }, /* odd parity */ + { "ap", 0 }, /* any parity */ + { "ec", 1 }, /* no echo */ + { "co", 0 }, /* console special */ + { "cb", 0 }, /* crt backspace */ + { "ck", 0 }, /* crt kill */ + { "ce", 0 }, /* crt erase */ + { "pe", 0 }, /* printer erase */ + { "rw", 1 }, /* don't use raw */ + { "xc", 1 }, /* don't ^X ctl chars */ + { "lc", 0 }, /* terminal las lower case */ + { "uc", 0 }, /* terminal has no lower case */ + { "ig", 0 }, /* ignore garbage */ + { "ps", 0 }, /* do port selector speed select */ + { "hc", 1 }, /* don't set hangup on close */ + { "ub", 0 }, /* unbuffered output */ + { "ab", 0 }, /* auto-baud detect with '\r' */ + { "dx", 0 }, /* set decctlq */ + { "np", 0 }, /* no parity at all (8bit chars) */ + { 0 } +}; diff --git a/libexec/getty/main.c b/libexec/getty/main.c new file mode 100644 index 0000000..c27ddf4 --- /dev/null +++ b/libexec/getty/main.c @@ -0,0 +1,549 @@ +/*- + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/20/93"; +#endif /* not lint */ + +#define USE_OLD_TTY + +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/resource.h> + +#include <ctype.h> +#include <ctype.h> +#include <fcntl.h> +#include <setjmp.h> +#include <sgtty.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> + +#include "gettytab.h" +#include "pathnames.h" +#include "extern.h" + +/* + * Set the amount of running time that getty should accumulate + * before deciding that something is wrong and exit. + */ +#define GETTY_TIMEOUT 60 /* seconds */ + +struct sgttyb tmode = { + 0, 0, CERASE, CKILL, 0 +}; +struct tchars tc = { + CINTR, CQUIT, CSTART, + CSTOP, CEOF, CBRK, +}; +struct ltchars ltc = { + CSUSP, CDSUSP, CRPRNT, + CFLUSH, CWERASE, CLNEXT +}; + +int crmod, digit, lower, upper; + +char hostname[MAXHOSTNAMELEN]; +char name[16]; +char dev[] = _PATH_DEV; +char ttyn[32]; +char *portselector(); +char *ttyname(); + +#define OBUFSIZ 128 +#define TABBUFSIZ 512 + +char defent[TABBUFSIZ]; +char tabent[TABBUFSIZ]; + +char *env[128]; + +char partab[] = { + 0001,0201,0201,0001,0201,0001,0001,0201, + 0202,0004,0003,0205,0005,0206,0201,0001, + 0201,0001,0001,0201,0001,0201,0201,0001, + 0001,0201,0201,0001,0201,0001,0001,0201, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0200, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0200,0000,0000,0200,0000,0200,0200,0000, + 0000,0200,0200,0000,0200,0000,0000,0201 +}; + +#define ERASE tmode.sg_erase +#define KILL tmode.sg_kill +#define EOT tc.t_eofc + +jmp_buf timeout; + +static void +dingdong() +{ + + alarm(0); + signal(SIGALRM, SIG_DFL); + longjmp(timeout, 1); +} + +jmp_buf intrupt; + +static void +interrupt() +{ + + signal(SIGINT, interrupt); + longjmp(intrupt, 1); +} + +/* + * Action to take when getty is running too long. + */ +void +timeoverrun(signo) + int signo; +{ + + syslog(LOG_ERR, "getty exiting due to excessive running time\n"); + exit(1); +} + +static int getname __P((void)); +static void oflush __P((void)); +static void prompt __P((void)); +static void putchr __P((int)); +static void putf __P((char *)); +static void putpad __P((char *)); +static void puts __P((char *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char **environ; + char *tname; + long allflags; + int repcnt = 0; + struct rlimit limit; + + signal(SIGINT, SIG_IGN); +/* + signal(SIGQUIT, SIG_DFL); +*/ + openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); + gethostname(hostname, sizeof(hostname)); + if (hostname[0] == '\0') + strcpy(hostname, "Amnesiac"); + + /* + * Limit running time to deal with broken or dead lines. + */ + (void)signal(SIGXCPU, timeoverrun); + limit.rlim_max = RLIM_INFINITY; + limit.rlim_cur = GETTY_TIMEOUT; + (void)setrlimit(RLIMIT_CPU, &limit); + + /* + * The following is a work around for vhangup interactions + * which cause great problems getting window systems started. + * If the tty line is "-", we do the old style getty presuming + * that the file descriptors are already set up for us. + * J. Gettys - MIT Project Athena. + */ + if (argc <= 2 || strcmp(argv[2], "-") == 0) + strcpy(ttyn, ttyname(0)); + else { + int i; + + strcpy(ttyn, dev); + strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); + if (strcmp(argv[0], "+") != 0) { + chown(ttyn, 0, 0); + chmod(ttyn, 0600); + revoke(ttyn); + /* + * Delay the open so DTR stays down long enough to be detected. + */ + sleep(2); + while ((i = open(ttyn, O_RDWR)) == -1) { + if (repcnt % 10 == 0) { + syslog(LOG_ERR, "%s: %m", ttyn); + closelog(); + } + repcnt++; + sleep(60); + } + login_tty(i); + } + } + + gettable("default", defent); + gendefaults(); + tname = "default"; + if (argc > 1) + tname = argv[1]; + for (;;) { + int off; + + gettable(tname, tabent); + if (OPset || EPset || APset) + APset++, OPset++, EPset++; + setdefaults(); + off = 0; + ioctl(0, TIOCFLUSH, &off); /* clear out the crap */ + ioctl(0, FIONBIO, &off); /* turn off non-blocking mode */ + ioctl(0, FIOASYNC, &off); /* ditto for async mode */ + if (IS) + tmode.sg_ispeed = speed(IS); + else if (SP) + tmode.sg_ispeed = speed(SP); + if (OS) + tmode.sg_ospeed = speed(OS); + else if (SP) + tmode.sg_ospeed = speed(SP); + tmode.sg_flags = setflags(0); + ioctl(0, TIOCSETP, &tmode); + setchars(); + ioctl(0, TIOCSETC, &tc); + if (HC) + ioctl(0, TIOCHPCL, 0); + if (AB) { + extern char *autobaud(); + + tname = autobaud(); + continue; + } + if (PS) { + tname = portselector(); + continue; + } + if (CL && *CL) + putpad(CL); + edithost(HE); + if (IM && *IM) + putf(IM); + if (setjmp(timeout)) { + tmode.sg_ispeed = tmode.sg_ospeed = 0; + ioctl(0, TIOCSETP, &tmode); + exit(1); + } + if (TO) { + signal(SIGALRM, dingdong); + alarm(TO); + } + if (getname()) { + register int i; + + oflush(); + alarm(0); + signal(SIGALRM, SIG_DFL); + if (name[0] == '-') { + puts("user names may not start with '-'."); + continue; + } + if (!(upper || lower || digit)) + continue; + allflags = setflags(2); + tmode.sg_flags = allflags & 0xffff; + allflags >>= 16; + if (crmod || NL) + tmode.sg_flags |= CRMOD; + if (upper || UC) + tmode.sg_flags |= LCASE; + if (lower || LC) + tmode.sg_flags &= ~LCASE; + ioctl(0, TIOCSETP, &tmode); + ioctl(0, TIOCSLTC, <c); + ioctl(0, TIOCLSET, &allflags); + signal(SIGINT, SIG_DFL); + for (i = 0; environ[i] != (char *)0; i++) + env[i] = environ[i]; + makeenv(&env[i]); + + /* + * this is what login was doing anyway. + * soon we rewrite getty completely. + */ + set_ttydefaults(0); + limit.rlim_max = RLIM_INFINITY; + limit.rlim_cur = RLIM_INFINITY; + (void)setrlimit(RLIMIT_CPU, &limit); + execle(LO, "login", "-p", name, (char *) 0, env); + syslog(LOG_ERR, "%s: %m", LO); + exit(1); + } + alarm(0); + signal(SIGALRM, SIG_DFL); + signal(SIGINT, SIG_IGN); + if (NX && *NX) + tname = NX; + } +} + +static int +getname() +{ + register int c; + register char *np; + char cs; + + /* + * Interrupt may happen if we use CBREAK mode + */ + if (setjmp(intrupt)) { + signal(SIGINT, SIG_IGN); + return (0); + } + signal(SIGINT, interrupt); + tmode.sg_flags = setflags(0); + ioctl(0, TIOCSETP, &tmode); + tmode.sg_flags = setflags(1); + prompt(); + if (PF > 0) { + oflush(); + sleep(PF); + PF = 0; + } + ioctl(0, TIOCSETP, &tmode); + crmod = digit = lower = upper = 0; + np = name; + for (;;) { + oflush(); + if (read(STDIN_FILENO, &cs, 1) <= 0) + exit(0); + if ((c = cs&0177) == 0) + return (0); + if (c == EOT) + exit(1); + if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { + putf("\r\n"); + break; + } + if (islower(c)) + lower = 1; + else if (isupper(c)) + upper = 1; + else if (c == ERASE || c == '#' || c == '\b') { + if (np > name) { + np--; + if (tmode.sg_ospeed >= B1200) + puts("\b \b"); + else + putchr(cs); + } + continue; + } else if (c == KILL || c == '@') { + putchr(cs); + putchr('\r'); + if (tmode.sg_ospeed < B1200) + putchr('\n'); + /* this is the way they do it down under ... */ + else if (np > name) + puts(" \r"); + prompt(); + np = name; + continue; + } else if (isdigit(c)) + digit++; + if (IG && (c <= ' ' || c > 0176)) + continue; + *np++ = c; + putchr(cs); + } + signal(SIGINT, SIG_IGN); + *np = 0; + if (c == '\r') + crmod = 1; + if (upper && !lower && !LC || UC) + for (np = name; *np; np++) + if (isupper(*np)) + *np = tolower(*np); + return (1); +} + +static +short tmspc10[] = { + 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 +}; + +static void +putpad(s) + register char *s; +{ + register pad = 0; + register mspc10; + + if (isdigit(*s)) { + while (isdigit(*s)) { + pad *= 10; + pad += *s++ - '0'; + } + pad *= 10; + if (*s == '.' && isdigit(s[1])) { + pad += s[1] - '0'; + s += 2; + } + } + + puts(s); + /* + * If no delay needed, or output speed is + * not comprehensible, then don't try to delay. + */ + if (pad == 0) + return; + if (tmode.sg_ospeed <= 0 || + tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) + return; + + /* + * Round up by a half a character frame, and then do the delay. + * Too bad there are no user program accessible programmed delays. + * Transmitting pad characters slows many terminals down and also + * loads the system. + */ + mspc10 = tmspc10[tmode.sg_ospeed]; + pad += mspc10 / 2; + for (pad /= mspc10; pad > 0; pad--) + putchr(*PC); +} + +static void +puts(s) + register char *s; +{ + while (*s) + putchr(*s++); +} + +char outbuf[OBUFSIZ]; +int obufcnt = 0; + +static void +putchr(cc) + int cc; +{ + char c; + + c = cc; + if (!NP) { + c |= partab[c&0177] & 0200; + if (OP) + c ^= 0200; + } + if (!UB) { + outbuf[obufcnt++] = c; + if (obufcnt >= OBUFSIZ) + oflush(); + } else + write(STDOUT_FILENO, &c, 1); +} + +static void +oflush() +{ + if (obufcnt) + write(STDOUT_FILENO, outbuf, obufcnt); + obufcnt = 0; +} + +static void +prompt() +{ + + putf(LM); + if (CO) + putchr('\n'); +} + +static void +putf(cp) + register char *cp; +{ + extern char editedhost[]; + time_t t; + char *slash, db[100]; + + while (*cp) { + if (*cp != '%') { + putchr(*cp++); + continue; + } + switch (*++cp) { + + case 't': + slash = strrchr(ttyn, '/'); + if (slash == (char *) 0) + puts(ttyn); + else + puts(&slash[1]); + break; + + case 'h': + puts(editedhost); + break; + + case 'd': { + static char fmt[] = "%l:% %P on %A, %d %B %Y"; + + fmt[4] = 'M'; /* I *hate* SCCS... */ + (void)time(&t); + (void)strftime(db, sizeof(db), fmt, localtime(&t)); + puts(db); + break; + } + + case '%': + putchr('%'); + break; + } + cp++; + } +} diff --git a/libexec/getty/pathnames.h b/libexec/getty/pathnames.h new file mode 100644 index 0000000..714a9cc --- /dev/null +++ b/libexec/getty/pathnames.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + */ + +#include <paths.h> + +#define _PATH_GETTYTAB "/etc/gettytab" +#define _PATH_LOGIN "/usr/bin/login" diff --git a/libexec/getty/subr.c b/libexec/getty/subr.c new file mode 100644 index 0000000..4a2abb3 --- /dev/null +++ b/libexec/getty/subr.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * Melbourne getty. + */ +#define USE_OLD_TTY +#include <stdlib.h> +#include <sgtty.h> +#include <string.h> +#include <unistd.h> + +#include "gettytab.h" +#include "extern.h" +#include "pathnames.h" + +extern struct sgttyb tmode; +extern struct tchars tc; +extern struct ltchars ltc; + +/* + * Get a table entry. + */ +void +gettable(name, buf) + char *name, *buf; +{ + register struct gettystrs *sp; + register struct gettynums *np; + register struct gettyflags *fp; + long n; + char *dba[2]; + dba[0] = _PATH_GETTYTAB; + dba[1] = 0; + + if (cgetent(&buf, dba, name) != 0) + return; + + for (sp = gettystrs; sp->field; sp++) + cgetstr(buf, sp->field, &sp->value); + for (np = gettynums; np->field; np++) { + if (cgetnum(buf, np->field, &n) == -1) + np->set = 0; + else { + np->set = 1; + np->value = n; + } + } + for (fp = gettyflags; fp->field; fp++) { + if (cgetcap(buf, fp->field, ':') == NULL) + fp->set = 0; + else { + fp->set = 1; + fp->value = 1 ^ fp->invrt; + } + } +#ifdef DEBUG + printf("name=\"%s\", buf=\"%s\"\n", name, buf); + for (sp = gettystrs; sp->field; sp++) + printf("cgetstr: %s=%s\n", sp->field, sp->value); + for (np = gettynums; np->field; np++) + printf("cgetnum: %s=%d\n", np->field, np->value); + for (fp = gettyflags; fp->field; fp++) + printf("cgetflags: %s='%c' set='%c'\n", fp->field, + fp->value + '0', fp->set + '0'); + exit(1); +#endif /* DEBUG */ +} + +void +gendefaults() +{ + register struct gettystrs *sp; + register struct gettynums *np; + register struct gettyflags *fp; + + for (sp = gettystrs; sp->field; sp++) + if (sp->value) + sp->defalt = sp->value; + for (np = gettynums; np->field; np++) + if (np->set) + np->defalt = np->value; + for (fp = gettyflags; fp->field; fp++) + if (fp->set) + fp->defalt = fp->value; + else + fp->defalt = fp->invrt; +} + +void +setdefaults() +{ + register struct gettystrs *sp; + register struct gettynums *np; + register struct gettyflags *fp; + + for (sp = gettystrs; sp->field; sp++) + if (!sp->value) + sp->value = sp->defalt; + for (np = gettynums; np->field; np++) + if (!np->set) + np->value = np->defalt; + for (fp = gettyflags; fp->field; fp++) + if (!fp->set) + fp->value = fp->defalt; +} + +static char ** +charnames[] = { + &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK, + &SU, &DS, &RP, &FL, &WE, &LN, 0 +}; + +static char * +charvars[] = { + &tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc, + &tc.t_quitc, &tc.t_startc, &tc.t_stopc, + &tc.t_eofc, &tc.t_brkc, <c.t_suspc, + <c.t_dsuspc, <c.t_rprntc, <c.t_flushc, + <c.t_werasc, <c.t_lnextc, 0 +}; + +void +setchars() +{ + register int i; + register char *p; + + for (i = 0; charnames[i]; i++) { + p = *charnames[i]; + if (p && *p) + *charvars[i] = *p; + else + *charvars[i] = '\377'; + } +} + +long +setflags(n) + int n; +{ + register long f; + + switch (n) { + case 0: + if (F0set) + return(F0); + break; + case 1: + if (F1set) + return(F1); + break; + default: + if (F2set) + return(F2); + break; + } + + f = 0; + + if (AP) + f |= ANYP; + else if (OP) + f |= ODDP; + else if (EP) + f |= EVENP; + + if (UC) + f |= LCASE; + + if (NL) + f |= CRMOD; + + f |= delaybits(); + + if (n == 1) { /* read mode flags */ + if (RW) + f |= RAW; + else + f |= CBREAK; + return (f); + } + + if (!HT) + f |= XTABS; + + if (n == 0) + return (f); + + if (CB) + f |= CRTBS; + + if (CE) + f |= CRTERA; + + if (CK) + f |= CRTKIL; + + if (PE) + f |= PRTERA; + + if (EC) + f |= ECHO; + + if (XC) + f |= CTLECH; + + if (DX) + f |= DECCTQ; + + return (f); +} + +struct delayval { + unsigned delay; /* delay in ms */ + int bits; +}; + +/* + * below are random guesses, I can't be bothered checking + */ + +struct delayval crdelay[] = { + { 1, CR1 }, + { 2, CR2 }, + { 3, CR3 }, + { 83, CR1 }, + { 166, CR2 }, + { 0, CR3 }, +}; + +struct delayval nldelay[] = { + { 1, NL1 }, /* special, calculated */ + { 2, NL2 }, + { 3, NL3 }, + { 100, NL2 }, + { 0, NL3 }, +}; + +struct delayval bsdelay[] = { + { 1, BS1 }, + { 0, 0 }, +}; + +struct delayval ffdelay[] = { + { 1, FF1 }, + { 1750, FF1 }, + { 0, FF1 }, +}; + +struct delayval tbdelay[] = { + { 1, TAB1 }, + { 2, TAB2 }, + { 3, XTABS }, /* this is expand tabs */ + { 100, TAB1 }, + { 0, TAB2 }, +}; + +int +delaybits() +{ + register int f; + + f = adelay(CD, crdelay); + f |= adelay(ND, nldelay); + f |= adelay(FD, ffdelay); + f |= adelay(TD, tbdelay); + f |= adelay(BD, bsdelay); + return (f); +} + +int +adelay(ms, dp) + register ms; + register struct delayval *dp; +{ + if (ms == 0) + return (0); + while (dp->delay && ms > dp->delay) + dp++; + return (dp->bits); +} + +char editedhost[32]; + +void +edithost(pat) + register char *pat; +{ + register char *host = HN; + register char *res = editedhost; + + if (!pat) + pat = ""; + while (*pat) { + switch (*pat) { + + case '#': + if (*host) + host++; + break; + + case '@': + if (*host) + *res++ = *host++; + break; + + default: + *res++ = *pat; + break; + + } + if (res == &editedhost[sizeof editedhost - 1]) { + *res = '\0'; + return; + } + pat++; + } + if (*host) + strncpy(res, host, sizeof editedhost - (res - editedhost) - 1); + else + *res = '\0'; + editedhost[sizeof editedhost - 1] = '\0'; +} + +struct speedtab { + int speed; + int uxname; +} speedtab[] = { + { 50, B50 }, + { 75, B75 }, + { 110, B110 }, + { 134, B134 }, + { 150, B150 }, + { 200, B200 }, + { 300, B300 }, + { 600, B600 }, + { 1200, B1200 }, + { 1800, B1800 }, + { 2400, B2400 }, + { 4800, B4800 }, + { 9600, B9600 }, + { 19200, EXTA }, + { 19, EXTA }, /* for people who say 19.2K */ + { 38400, EXTB }, + { 38, EXTB }, + { 7200, EXTB }, /* alternative */ + { 0 } +}; + +int +speed(val) + int val; +{ + register struct speedtab *sp; + + if (val <= 15) + return (val); + + for (sp = speedtab; sp->speed; sp++) + if (sp->speed == val) + return (sp->uxname); + + return (B300); /* default in impossible cases */ +} + +void +makeenv(env) + char *env[]; +{ + static char termbuf[128] = "TERM="; + register char *p, *q; + register char **ep; + + ep = env; + if (TT && *TT) { + strcat(termbuf, TT); + *ep++ = termbuf; + } + if (p = EV) { + q = p; + while (q = strchr(q, ',')) { + *q++ = '\0'; + *ep++ = p; + p = q; + } + if (*p) + *ep++ = p; + } + *ep = (char *)0; +} + +/* + * This speed select mechanism is written for the Develcon DATASWITCH. + * The Develcon sends a string of the form "B{speed}\n" at a predefined + * baud rate. This string indicates the user's actual speed. + * The routine below returns the terminal type mapped from derived speed. + */ +struct portselect { + char *ps_baud; + char *ps_type; +} portspeeds[] = { + { "B110", "std.110" }, + { "B134", "std.134" }, + { "B150", "std.150" }, + { "B300", "std.300" }, + { "B600", "std.600" }, + { "B1200", "std.1200" }, + { "B2400", "std.2400" }, + { "B4800", "std.4800" }, + { "B9600", "std.9600" }, + { "B19200", "std.19200" }, + { 0 } +}; + +char * +portselector() +{ + char c, baud[20], *type = "default"; + register struct portselect *ps; + int len; + + alarm(5*60); + for (len = 0; len < sizeof (baud) - 1; len++) { + if (read(STDIN_FILENO, &c, 1) <= 0) + break; + c &= 0177; + if (c == '\n' || c == '\r') + break; + if (c == 'B') + len = 0; /* in case of leading garbage */ + baud[len] = c; + } + baud[len] = '\0'; + for (ps = portspeeds; ps->ps_baud; ps++) + if (strcmp(ps->ps_baud, baud) == 0) { + type = ps->ps_type; + break; + } + sleep(2); /* wait for connection to complete */ + return (type); +} + +/* + * This auto-baud speed select mechanism is written for the Micom 600 + * portselector. Selection is done by looking at how the character '\r' + * is garbled at the different speeds. + */ +#include <sys/time.h> + +char * +autobaud() +{ + int rfds; + struct timeval timeout; + char c, *type = "9600-baud"; + int null = 0; + + ioctl(0, TIOCFLUSH, &null); + rfds = 1 << 0; + timeout.tv_sec = 5; + timeout.tv_usec = 0; + if (select(32, (fd_set *)&rfds, (fd_set *)NULL, + (fd_set *)NULL, &timeout) <= 0) + return (type); + if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char)) + return (type); + timeout.tv_sec = 0; + timeout.tv_usec = 20; + (void) select(32, (fd_set *)NULL, (fd_set *)NULL, + (fd_set *)NULL, &timeout); + ioctl(0, TIOCFLUSH, &null); + switch (c & 0377) { + + case 0200: /* 300-baud */ + type = "300-baud"; + break; + + case 0346: /* 1200-baud */ + type = "1200-baud"; + break; + + case 015: /* 2400-baud */ + case 0215: + type = "2400-baud"; + break; + + default: /* 4800-baud */ + type = "4800-baud"; + break; + + case 0377: /* 9600-baud */ + type = "9600-baud"; + break; + } + return (type); +} diff --git a/libexec/getty/ttys.5 b/libexec/getty/ttys.5 new file mode 100644 index 0000000..cbbdbb6 --- /dev/null +++ b/libexec/getty/ttys.5 @@ -0,0 +1,139 @@ +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ttys.5 8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt TTYS 5 +.Os +.Sh NAME +.Nm ttys +.Nd terminal initialization information +.Sh DESCRIPTION +The file +.Nm ttys +contains information that is used by various routines to initialize +and control the use of terminal special files. +This information is read with the +.Xr getttyent 3 +library routines. +There is one line in the +.Nm ttys +file per special device file. +Fields are separated by tabs and/or spaces. +Fields comprised of more than one word should be enclosed in double +quotes (``"''). +Blank lines and comments may appear anywhere in the file; comments +are delimited by hash marks (``#'') and new lines. +Any unspecified fields will default to null. +.Pp +The first field is the +name of the terminal special file as it is found in +.Pa /dev . +.Pp +The second field of the file is the command to execute for the line, +usually +.Xr getty 8 , +which initializes and opens the line, setting the speed, waiting for +a user name and executing the +.Xr login 1 +program. +It can be, however, any desired command, for example +the start up for a window system terminal emulator or some other +daemon process, and can contain multiple words if quoted. +.Pp +The third field is the type of terminal usually connected to that +tty line, normally the one found in the +.Xr termcap 5 +data base file. +The environment variable +.Dv TERM +is initialized with the value by +either +.Xr getty 8 +or +.Xr login 1 . +.Pp +The remaining fields set flags in the +.Fa ty_status +entry (see +.Xr getttyent 3 ) +or specify a window system process that +.Xr init 8 +will maintain for the terminal line. +.Pp +As flag values, the strings ``on'' and ``off'' specify that +.Xr init +should (should not) execute the command given in the second field, +while ``secure'' (if ``on'' is also specified) allows users with a +uid of 0 to login on +this line. +These flag fields should not be quoted. +.Pp +The string ``window='' may be followed by a quoted command +string which +.Xr init +will execute +.Em before +starting the command specified by the second field. +.Sh EXAMPLES +.Bd -literal +# root login on console at 1200 baud +console "/usr/libexec/getty std.1200" vt100 on secure +# dialup at 1200 baud, no root logins +ttyd0 "/usr/libexec/getty d1200" dialup on # 555-1234 +# Mike's terminal: hp2621 +ttyh0 "/usr/libexec/getty std.9600" hp2621-nl on # 457 Evans +# John's terminal: vt100 +ttyh1 "/usr/libexec/getty std.9600" vt100 on # 459 Evans +# terminal emulate/window system +ttyv0 "/usr/new/xterm -L :0" vs100 on window="/usr/new/Xvs100 0" +# Network pseudo ttys -- don't enable getty +ttyp0 none network +ttyp1 none network off +.Ed +.Sh FILES +.Bl -tag -width /etc/ttys -compact +.It Pa /etc/ttys +.El +.Sh SEE ALSO +.Xr login 1 , +.Xr getttyent 3 , +.Xr ttyslot 3 , +.Xr gettytab 5 , +.Xr termcap 5 , +.Xr getty 8 , +.Xr init 8 +.Sh HISTORY +A +.Nm +file appeared in +.At v6 . diff --git a/libexec/rbootd/Makefile b/libexec/rbootd/Makefile new file mode 100644 index 0000000..6e377fc --- /dev/null +++ b/libexec/rbootd/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 8.1 (Berkeley) 6/4/93 + +PROG= rbootd +SRCS= bpf.c conf.c parseconf.c rbootd.c rmpproto.c utils.c +MAN8= rbootd.0 + +afterinstall: + (cd ${.CURDIR}/bootdir && install -c -o ${BINOWN} -g ${BINGRP} \ + -m 444 * ${DESTDIR}/usr/mdec/) + +.include <bsd.prog.mk> diff --git a/libexec/rbootd/bpf.c b/libexec/rbootd/bpf.c new file mode 100644 index 0000000..7ecd419 --- /dev/null +++ b/libexec/rbootd/bpf.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: bpf.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)bpf.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/socket.h> + +#include <net/if.h> +#include <net/bpf.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include "defs.h" +#include "pathnames.h" + +static int BpfFd = -1; +static unsigned BpfLen = 0; +static u_char *BpfPkt = NULL; + +/* +** BpfOpen -- Open and initialize a BPF device. +** +** Parameters: +** None. +** +** Returns: +** File descriptor of opened BPF device (for select() etc). +** +** Side Effects: +** If an error is encountered, the program terminates here. +*/ +int +BpfOpen() +{ + struct ifreq ifr; + char bpfdev[32]; + int n = 0; + + /* + * Open the first available BPF device. + */ + do { + (void) sprintf(bpfdev, _PATH_BPF, n++); + BpfFd = open(bpfdev, O_RDWR); + } while (BpfFd < 0 && (errno == EBUSY || errno == EPERM)); + + if (BpfFd < 0) { + syslog(LOG_ERR, "bpf: no available devices: %m"); + Exit(0); + } + + /* + * Set interface name for bpf device, get data link layer + * type and make sure it's type Ethernet. + */ + (void) strncpy(ifr.ifr_name, IntfName, sizeof(ifr.ifr_name)); + if (ioctl(BpfFd, BIOCSETIF, (caddr_t)&ifr) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName); + Exit(0); + } + + /* + * Make sure we are dealing with an Ethernet device. + */ + if (ioctl(BpfFd, BIOCGDLT, (caddr_t)&n) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCGDLT): %m"); + Exit(0); + } + if (n != DLT_EN10MB) { + syslog(LOG_ERR,"bpf: %s: data-link type %d unsupported", + IntfName, n); + Exit(0); + } + + /* + * On read(), return packets immediately (do not buffer them). + */ + n = 1; + if (ioctl(BpfFd, BIOCIMMEDIATE, (caddr_t)&n) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCIMMEDIATE): %m"); + Exit(0); + } + + /* + * Try to enable the chip/driver's multicast address filter to + * grab our RMP address. If this fails, try promiscuous mode. + * If this fails, there's no way we are going to get any RMP + * packets so just exit here. + */ +#ifdef MSG_EOR + ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; +#endif + ifr.ifr_addr.sa_family = AF_UNSPEC; + bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); + if (ioctl(BpfFd, SIOCADDMULTI, (caddr_t)&ifr) < 0) { + syslog(LOG_WARNING, + "bpf: can't add mcast addr (%m), setting promiscuous mode"); + + if (ioctl(BpfFd, BIOCPROMISC, (caddr_t)0) < 0) { + syslog(LOG_ERR, "bpf: can't set promiscuous mode: %m"); + Exit(0); + } + } + + /* + * Ask BPF how much buffer space it requires and allocate one. + */ + if (ioctl(BpfFd, BIOCGBLEN, (caddr_t)&BpfLen) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCGBLEN): %m"); + Exit(0); + } + if (BpfPkt == NULL) + BpfPkt = (u_char *)malloc(BpfLen); + + if (BpfPkt == NULL) { + syslog(LOG_ERR, "bpf: out of memory (%u bytes for bpfpkt)", + BpfLen); + Exit(0); + } + + /* + * Write a little program to snarf RMP Boot packets and stuff + * it down BPF's throat (i.e. set up the packet filter). + */ + { +#define RMP ((struct rmp_packet *)0) + static struct bpf_insn bpf_insn[] = { + { BPF_LD|BPF_B|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dsap }, + { BPF_JMP|BPF_JEQ|BPF_K, 0, 5, IEEE_DSAP_HP }, + { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.cntrl }, + { BPF_JMP|BPF_JEQ|BPF_K, 0, 3, IEEE_CNTL_HP }, + { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dxsap }, + { BPF_JMP|BPF_JEQ|BPF_K, 0, 1, HPEXT_DXSAP }, + { BPF_RET|BPF_K, 0, 0, RMP_MAX_PACKET }, + { BPF_RET|BPF_K, 0, 0, 0x0 } + }; +#undef RMP + static struct bpf_program bpf_pgm = { + sizeof(bpf_insn)/sizeof(bpf_insn[0]), bpf_insn + }; + + if (ioctl(BpfFd, BIOCSETF, (caddr_t)&bpf_pgm) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCSETF): %m"); + Exit(0); + } + } + + return(BpfFd); +} + +/* +** BPF GetIntfName -- Return the name of a network interface attached to +** the system, or 0 if none can be found. The interface +** must be configured up; the lowest unit number is +** preferred; loopback is ignored. +** +** Parameters: +** errmsg - if no network interface found, *errmsg explains why. +** +** Returns: +** A (static) pointer to interface name, or NULL on error. +** +** Side Effects: +** None. +*/ +char * +BpfGetIntfName(errmsg) + char **errmsg; +{ + struct ifreq ibuf[8], *ifrp, *ifend, *mp; + struct ifconf ifc; + int fd; + int minunit, n; + char *cp; + static char device[sizeof(ifrp->ifr_name)]; + static char errbuf[128] = "No Error!"; + + if (errmsg != NULL) + *errmsg = errbuf; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + (void) strcpy(errbuf, "bpf: socket: %m"); + return(NULL); + } + ifc.ifc_len = sizeof ibuf; + ifc.ifc_buf = (caddr_t)ibuf; + +#ifdef OSIOCGIFCONF + if (ioctl(fd, OSIOCGIFCONF, (char *)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + (void) strcpy(errbuf, "bpf: ioctl(OSIOCGIFCONF): %m"); + return(NULL); + } +#else + if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFCONF): %m"); + return(NULL); + } +#endif + ifrp = ibuf; + ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); + + mp = 0; + minunit = 666; + for (; ifrp < ifend; ++ifrp) { + if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) { + (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFFLAGS): %m"); + return(NULL); + } + + /* + * If interface is down or this is the loopback interface, + * ignore it. + */ + if ((ifrp->ifr_flags & IFF_UP) == 0 || +#ifdef IFF_LOOPBACK + (ifrp->ifr_flags & IFF_LOOPBACK)) +#else + (strcmp(ifrp->ifr_name, "lo0") == 0)) +#endif + continue; + + for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) + ; + n = atoi(cp); + if (n < minunit) { + minunit = n; + mp = ifrp; + } + } + + (void) close(fd); + if (mp == 0) { + (void) strcpy(errbuf, "bpf: no interfaces found"); + return(NULL); + } + + (void) strcpy(device, mp->ifr_name); + return(device); +} + +/* +** BpfRead -- Read packets from a BPF device and fill in `rconn'. +** +** Parameters: +** rconn - filled in with next packet. +** doread - is True if we can issue a read() syscall. +** +** Returns: +** True if `rconn' contains a new packet, False otherwise. +** +** Side Effects: +** None. +*/ +int +BpfRead(rconn, doread) + RMPCONN *rconn; + int doread; +{ + register int datlen, caplen, hdrlen; + static u_char *bp = NULL, *ep = NULL; + int cc; + + /* + * The read() may block, or it may return one or more packets. + * We let the caller decide whether or not we can issue a read(). + */ + if (doread) { + if ((cc = read(BpfFd, (char *)BpfPkt, (int)BpfLen)) < 0) { + syslog(LOG_ERR, "bpf: read: %m"); + return(0); + } else { + bp = BpfPkt; + ep = BpfPkt + cc; + } + } + +#define bhp ((struct bpf_hdr *)bp) + /* + * If there is a new packet in the buffer, stuff it into `rconn' + * and return a success indication. + */ + if (bp < ep) { + datlen = bhp->bh_datalen; + caplen = bhp->bh_caplen; + hdrlen = bhp->bh_hdrlen; + + if (caplen != datlen) + syslog(LOG_ERR, + "bpf: short packet dropped (%d of %d bytes)", + caplen, datlen); + else if (caplen > sizeof(struct rmp_packet)) + syslog(LOG_ERR, "bpf: large packet dropped (%d bytes)", + caplen); + else { + rconn->rmplen = caplen; + bcopy((char *)&bhp->bh_tstamp, (char *)&rconn->tstamp, + sizeof(struct timeval)); + bcopy((char *)bp + hdrlen, (char *)&rconn->rmp, caplen); + } + bp += BPF_WORDALIGN(caplen + hdrlen); + return(1); + } +#undef bhp + + return(0); +} + +/* +** BpfWrite -- Write packet to BPF device. +** +** Parameters: +** rconn - packet to send. +** +** Returns: +** True if write succeeded, False otherwise. +** +** Side Effects: +** None. +*/ +int +BpfWrite(rconn) + RMPCONN *rconn; +{ + if (write(BpfFd, (char *)&rconn->rmp, rconn->rmplen) < 0) { + syslog(LOG_ERR, "write: %s: %m", EnetStr(rconn)); + return(0); + } + + return(1); +} + +/* +** BpfClose -- Close a BPF device. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** None. +*/ +void +BpfClose() +{ + struct ifreq ifr; + + if (BpfPkt != NULL) { + free((char *)BpfPkt); + BpfPkt = NULL; + } + + if (BpfFd == -1) + return; + +#ifdef MSG_EOR + ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; +#endif + ifr.ifr_addr.sa_family = AF_UNSPEC; + bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); + if (ioctl(BpfFd, SIOCDELMULTI, (caddr_t)&ifr) < 0) + (void) ioctl(BpfFd, BIOCPROMISC, (caddr_t)0); + + (void) close(BpfFd); + BpfFd = -1; +} diff --git a/libexec/rbootd/conf.c b/libexec/rbootd/conf.c new file mode 100644 index 0000000..b890eea --- /dev/null +++ b/libexec/rbootd/conf.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)conf.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: conf.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)conf.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/time.h> + +#include <stdio.h> +#include "defs.h" +#include "pathnames.h" + +/* +** Define (and possibly initialize) global variables here. +** +** Caveat: +** The maximum number of bootable files (`char *BootFiles[]') is +** limited to C_MAXFILE (i.e. the maximum number of files that +** can be spec'd in the configuration file). This was done to +** simplify the boot file search code. +*/ + +char *ProgName; /* path-stripped argv[0] */ +char MyHost[MAXHOSTNAMELEN+1]; /* host name */ +int MyPid; /* process id */ +int DebugFlg = 0; /* set true if debugging */ +int BootAny = 0; /* set true if we boot anyone */ + +char *ConfigFile = NULL; /* configuration file */ +char *DfltConfig = _PATH_RBOOTDCONF; /* default configuration file */ +char *PidFile = _PATH_RBOOTDPID; /* file w/pid of server */ +char *BootDir = _PATH_RBOOTDLIB; /* directory w/boot files */ +char *DbgFile = _PATH_RBOOTDDBG; /* debug output file */ + +FILE *DbgFp = NULL; /* debug file pointer */ +char *IntfName = NULL; /* intf we are attached to */ + +u_short SessionID = 0; /* generated session ID */ + +char *BootFiles[C_MAXFILE]; /* list of boot files */ + +CLIENT *Clients = NULL; /* list of addrs we'll accept */ +RMPCONN *RmpConns = NULL; /* list of active connections */ + +char RmpMcastAddr[RMP_ADDRLEN] = RMP_ADDR; /* RMP multicast address */ diff --git a/libexec/rbootd/defs.h b/libexec/rbootd/defs.h new file mode 100644 index 0000000..a2e0cd0 --- /dev/null +++ b/libexec/rbootd/defs.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: defs.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#include "rmp.h" +#include "rmp_var.h" + +/* +** Common #define's and external variables. All other files should +** include this. +*/ + +/* + * This may be defined in <sys/param.h>, if not, it's defined here. + */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +/* + * SIGUSR1 and SIGUSR2 are defined in <signal.h> for 4.3BSD systems. + */ +#ifndef SIGUSR1 +#define SIGUSR1 SIGEMT +#endif +#ifndef SIGUSR2 +#define SIGUSR2 SIGFPE +#endif + +/* + * These can be faster & more efficient than strcmp()/strncmp()... + */ +#define STREQN(s1,s2) ((*s1 == *s2) && (strcmp(s1,s2) == 0)) +#define STRNEQN(s1,s2,n) ((*s1 == *s2) && (strncmp(s1,s2,n) == 0)) + +/* + * Configuration file limitations. + */ +#define C_MAXFILE 10 /* max number of boot-able files */ +#define C_LINELEN 1024 /* max length of line */ + +/* + * Direction of packet (used as argument to DispPkt). + */ +#define DIR_RCVD 0 +#define DIR_SENT 1 +#define DIR_NONE 2 + +/* + * These need not be functions, so... + */ +#define FreeStr(str) free(str) +#define FreeClient(cli) free(cli) +#define GenSessID() (++SessionID ? SessionID: ++SessionID) + +/* + * Converting an Ethernet address to a string is done in many routines. + * Using `rmp.hp_hdr.saddr' works because this field is *never* changed; + * it will *always* contain the source address of the packet. + */ +#define EnetStr(rptr) GetEtherAddr(&(rptr)->rmp.hp_hdr.saddr[0]) + +/* + * Every machine we can boot will have one of these allocated for it + * (unless there are no restrictions on who we can boot). + */ +typedef struct client_s { + u_char addr[RMP_ADDRLEN]; /* addr of machine */ + char *files[C_MAXFILE]; /* boot-able files */ + struct client_s *next; /* ptr to next */ +} CLIENT; + +/* + * Every active connection has one of these allocated for it. + */ +typedef struct rmpconn_s { + struct rmp_packet rmp; /* RMP packet */ + int rmplen; /* length of packet */ + struct timeval tstamp; /* last time active */ + int bootfd; /* open boot file */ + struct rmpconn_s *next; /* ptr to next */ +} RMPCONN; + +/* + * All these variables are defined in "conf.c". + */ +extern char *ProgName; /* path-stripped argv[0] */ +extern char MyHost[]; /* this hosts' name */ +extern int MyPid; /* this processes' ID */ +extern int DebugFlg; /* set true if debugging */ +extern int BootAny; /* set true if we can boot anyone */ + +extern char *ConfigFile; /* configuration file */ +extern char *DfltConfig; /* default configuration file */ +extern char *DbgFile; /* debug output file */ +extern char *PidFile; /* file containing pid of server */ +extern char *BootDir; /* directory w/boot files */ + +extern FILE *DbgFp; /* debug file pointer */ +extern char *IntfName; /* interface we are attached to */ + +extern u_short SessionID; /* generated session ID */ + +extern char *BootFiles[]; /* list of boot files */ + +extern CLIENT *Clients; /* list of addrs we'll accept */ +extern RMPCONN *RmpConns; /* list of active connections */ + +extern char RmpMcastAddr[]; /* RMP multicast address */ + +void AddConn __P((RMPCONN *)); +int BootDone __P((RMPCONN *)); +void BpfClose __P((void)); +char *BpfGetIntfName __P((char **)); +int BpfOpen __P((void)); +int BpfRead __P((RMPCONN *, int)); +int BpfWrite __P((RMPCONN *)); +void DebugOff __P((int)); +void DebugOn __P((int)); +void DispPkt __P((RMPCONN *, int)); +void DoTimeout __P((void)); +void DspFlnm __P((u_int, char *)); +void Exit __P((int)); +CLIENT *FindClient __P((RMPCONN *)); +RMPCONN *FindConn __P((RMPCONN *)); +void FreeClients __P((void)); +void FreeConn __P((RMPCONN *)); +void FreeConns __P((void)); +int GetBootFiles __P((void)); +char *GetEtherAddr __P((u_char *)); +CLIENT *NewClient __P((u_char *)); +RMPCONN *NewConn __P((RMPCONN *)); +char *NewStr __P((char *)); +u_char *ParseAddr __P((char *)); +int ParseConfig __P((void)); +void ProcessPacket __P((RMPCONN *, CLIENT *)); +void ReConfig __P((int)); +void RemoveConn __P((RMPCONN *)); +int SendBootRepl __P((struct rmp_packet *, RMPCONN *, char *[])); +int SendFileNo __P((struct rmp_packet *, RMPCONN *, char *[])); +int SendPacket __P((RMPCONN *)); +int SendReadRepl __P((RMPCONN *)); +int SendServerID __P((RMPCONN *)); diff --git a/libexec/rbootd/parseconf.c b/libexec/rbootd/parseconf.c new file mode 100644 index 0000000..d00436f --- /dev/null +++ b/libexec/rbootd/parseconf.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)parseconf.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: parseconf.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)parseconf.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/stat.h> + +#include <ctype.h> +#include <dirent.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include "defs.h" + +/* +** ParseConfig -- parse the config file into linked list of clients. +** +** Parameters: +** None. +** +** Returns: +** 1 on success, 0 otherwise. +** +** Side Effects: +** - Linked list of clients will be (re)allocated. +** +** Warnings: +** - GetBootFiles() must be called before this routine +** to create a linked list of default boot files. +*/ +int +ParseConfig() +{ + FILE *fp; + CLIENT *client; + u_char *addr; + char line[C_LINELEN]; + register char *cp, *bcp; + register int i, j; + int omask, linecnt = 0; + + if (BootAny) /* ignore config file */ + return(1); + + FreeClients(); /* delete old list of clients */ + + if ((fp = fopen(ConfigFile, "r")) == NULL) { + syslog(LOG_ERR, "ParseConfig: can't open config file (%s)", + ConfigFile); + return(0); + } + + /* + * We've got to block SIGHUP to prevent reconfiguration while + * dealing with the linked list of Clients. This can be done + * when actually linking the new client into the list, but + * this could have unexpected results if the server was HUP'd + * whilst reconfiguring. Hence, it is done here. + */ + omask = sigblock(sigmask(SIGHUP)); + + /* + * GETSTR positions `bcp' at the start of the current token, + * and null terminates it. `cp' is positioned at the start + * of the next token. spaces & commas are separators. + */ +#define GETSTR while (isspace(*cp) || *cp == ',') cp++; \ + bcp = cp; \ + while (*cp && *cp!=',' && !isspace(*cp)) cp++; \ + if (*cp) *cp++ = '\0' + + /* + * For each line, parse it into a new CLIENT struct. + */ + while (fgets(line, C_LINELEN, fp) != NULL) { + linecnt++; /* line counter */ + + if (*line == '\0' || *line == '#') /* ignore comment */ + continue; + + if ((cp = index(line,'#')) != NULL) /* trash comments */ + *cp = '\0'; + + cp = line; /* init `cp' */ + GETSTR; /* get RMP addr */ + if (bcp == cp) /* all delimiters */ + continue; + + /* + * Get an RMP address from a string. Abort on failure. + */ + if ((addr = ParseAddr(bcp)) == NULL) { + syslog(LOG_ERR, + "ParseConfig: line %d: cant parse <%s>", + linecnt, bcp); + continue; + } + + if ((client = NewClient(addr)) == NULL) /* alloc new client */ + continue; + + GETSTR; /* get first file */ + + /* + * If no boot files are spec'd, use the default list. + * Otherwise, validate each file (`bcp') against the + * list of boot-able files. + */ + i = 0; + if (bcp == cp) /* no files spec'd */ + for (; i < C_MAXFILE && BootFiles[i] != NULL; i++) + client->files[i] = BootFiles[i]; + else { + do { + /* + * For each boot file spec'd, make sure it's + * in our list. If so, include a pointer to + * it in the CLIENT's list of boot files. + */ + for (j = 0; ; j++) { + if (j==C_MAXFILE||BootFiles[j]==NULL) { + syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)", + linecnt, bcp); + break; + } + if (STREQN(BootFiles[j], bcp)) { + if (i < C_MAXFILE) + client->files[i++] = + BootFiles[j]; + else + syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)", + linecnt, bcp); + break; + } + } + GETSTR; /* get next file */ + } while (bcp != cp); + + /* + * Restricted list of boot files were spec'd, + * however, none of them were found. Since we + * apparently cant let them boot "just anything", + * the entire record is invalidated. + */ + if (i == 0) { + FreeClient(client); + continue; + } + } + + /* + * Link this client into the linked list of clients. + * SIGHUP has already been blocked. + */ + if (Clients) + client->next = Clients; + Clients = client; + } + + (void) fclose(fp); /* close config file */ + + (void) sigsetmask(omask); /* reset signal mask */ + + return(1); /* return success */ +} + +/* +** ParseAddr -- Parse a string containing an RMP address. +** +** This routine is fairly liberal at parsing an RMP address. The +** address must contain 6 octets consisting of between 0 and 2 hex +** chars (upper/lower case) separated by colons. If two colons are +** together (e.g. "::", the octet between them is recorded as being +** zero. Hence, the following addrs are all valid and parse to the +** same thing: +** +** 08:00:09:00:66:ad 8::9:0:66:AD 8::9::66:aD +** +** For clarity, an RMP address is really an Ethernet address, but +** since the HP boot code uses IEEE 802.3, it's really an IEEE +** 802.3 address. Of course, all of these are identical. +** +** Parameters: +** str - string representation of an RMP address. +** +** Returns: +** pointer to a static array of RMP_ADDRLEN bytes. +** +** Side Effects: +** None. +** +** Warnings: +** - The return value points to a static buffer; it must +** be copied if it's to be saved. +** - For speed, we assume a u_char consists of 8 bits. +*/ +u_char * +ParseAddr(str) + char *str; +{ + static u_char addr[RMP_ADDRLEN]; + register char *cp; + register unsigned i; + register int part, subpart; + + bzero((char *)&addr[0], RMP_ADDRLEN); /* zero static buffer */ + + part = subpart = 0; + for (cp = str; *cp; cp++) { + /* + * A colon (`:') must be used to delimit each octet. + */ + if (*cp == ':') { + if (++part == RMP_ADDRLEN) /* too many parts */ + return(NULL); + subpart = 0; + continue; + } + + /* + * Convert hex character to an integer. + */ + if (isdigit(*cp)) + i = *cp - '0'; + else { + i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10; + if (i < 10 || i > 15) /* not a hex char */ + return(NULL); + } + + if (subpart++) { + if (subpart > 2) /* too many hex chars */ + return(NULL); + addr[part] <<= 4; + } + addr[part] |= i; + } + + if (part != (RMP_ADDRLEN-1)) /* too few parts */ + return(NULL); + + return(&addr[0]); +} + +/* +** GetBootFiles -- record list of files in current (boot) directory. +** +** Parameters: +** None. +** +** Returns: +** Number of boot files on success, 0 on failure. +** +** Side Effects: +** Strings in `BootFiles' are freed/allocated. +** +** Warnings: +** - After this routine is called, ParseConfig() must be +** called to re-order it's list of boot file pointers. +*/ +int +GetBootFiles() +{ + DIR *dfd; + struct stat statb; + register struct dirent *dp; + register int i; + + /* + * Free the current list of boot files. + */ + for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) { + FreeStr(BootFiles[i]); + BootFiles[i] = NULL; + } + + /* + * Open current directory to read boot file names. + */ + if ((dfd = opendir(".")) == NULL) { /* open BootDir */ + syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n", + BootDir); + return(0); + } + + /* + * Read each boot file name and allocate space for it in the + * list of boot files (BootFiles). All boot files read after + * C_MAXFILE will be ignored. + */ + i = 0; + for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) { + if (stat(dp->d_name, &statb) < 0 || + (statb.st_mode & S_IFMT) != S_IFREG) + continue; + if (i == C_MAXFILE) + syslog(LOG_ERR, + "GetBootFiles: too many boot files (%s ignored)", + dp->d_name); + else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL) + i++; + } + + (void) closedir(dfd); /* close BootDir */ + + if (i == 0) /* cant find any boot files */ + syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir); + + return(i); +} diff --git a/libexec/rbootd/pathnames.h b/libexec/rbootd/pathnames.h new file mode 100644 index 0000000..d960dce --- /dev/null +++ b/libexec/rbootd/pathnames.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: pathnames.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#define _PATH_BPF "/dev/bpf%d" +#define _PATH_RBOOTDCONF "/etc/rbootd.conf" +#define _PATH_RBOOTDDBG "/tmp/rbootd.dbg" +#define _PATH_RBOOTDLIB "/usr/mdec/rbootd" +#define _PATH_RBOOTDPID "/var/run/rbootd.pid" diff --git a/libexec/rbootd/rbootd.8 b/libexec/rbootd/rbootd.8 new file mode 100644 index 0000000..f4eb364 --- /dev/null +++ b/libexec/rbootd/rbootd.8 @@ -0,0 +1,156 @@ +.\" Copyright (c) 1988, 1992 The University of Utah and the Center +.\" for Software Science (CSS). +.\" Copyright (c) 1992, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Center for Software Science of the University of Utah Computer +.\" Science Department. CSS requests users of this software to return +.\" to css-dist@cs.utah.edu any improvements that they make and grant +.\" CSS redistribution rights. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rbootd.8 8.2 (Berkeley) 12/11/93 +.\" +.\" Utah $Hdr: rbootd.man 3.1 92/07/06$ +.\" Author: Jeff Forys, University of Utah CSS +.\" +.Dd "December 11, 1993" +.Dt RBOOTD 8 +.Os +.Sh NAME +.Nm rbootd +.Nd HP remote boot server +.Sh SYNOPSIS +.Nm rbootd +.Op Fl ad +.Op Fl i Ar interface +.Op config_file +.Sh DESCRIPTION +The +.Nm rbootd +utility services boot requests from Hewlett-Packard workstations over a +local area network. +All boot files must reside in the boot file directory; further, if a +client supplies path information in its boot request, it will be silently +stripped away before processing. +By default, +.Nm rbootd +only responds to requests from machines listed in its configuration file. +.Pp +The options are as follows: +.Bl -tag -width Fl +.It Fl a +Respond to boot requests from any machine. +The configuration file is ignored if this option is specified. +.It Fl d +Run +.Nm rbootd +in debug mode. +Packets sent and received are displayed to the terminal. +.It Fl i Ar interface +Service boot requests on specified interface. +If unspecified, +.Nm rbootd +searches the system interface list for the lowest numbered, configured +``up'' interface (excluding loopback). +Ties are broken by choosing the earliest match. +.El +.Pp +Specifying +.Ar config_file +on the command line causes +.Nm rbootd +to use a different configuration file from the default. +.Pp +The configuration file is a text file where each line describes a particular +machine. +A line must start with a machine's Ethernet address followed by an optional +list of boot file names. +An Ethernet address is specified in hexadecimal with each of its six octets +separated by a colon. +The boot file names come from the boot file directory. +The ethernet address and boot file(s) must be separated by white-space +and/or comma characters. +A pound sign causes the remainder of a line to be ignored. +.Pp +Here is a sample configuration file: +.Bl -column 08:00:09:0:66:ad SYSHPBSD,SYSHPUX "# vandy (anything)" +.It # +.It # ethernet addr boot file(s) comments +.It # +.It 08:00:09:0:66:ad SYSHPBSD # snake (4.3BSD) +.It 08:00:09:0:59:5b # vandy (anything) +.It 8::9:1:C6:75 SYSHPBSD,SYSHPUX # jaguar (either) +.El +.Pp +.Nm Rbootd +logs status and error messages via +.Xr syslog 3 . +A startup message is always logged, and in the case of fatal errors (or +deadly signals) a message is logged announcing the server's termination. +In general, a non-fatal error is handled by ignoring the event that caused +it (e.g. an invalid Ethernet address in the config file causes that line +to be invalidated). +.Pp +The following signals have the specified effect when sent to the server +process using the +.Xr kill 1 +command: +.Bl -tag -width SIGUSR1 -offset -compact +.It SIGHUP +Drop all active connections and reconfigure. +.It SIGUSR1 +Turn on debugging, do nothing if already on. +.It SIGUSR2 +Turn off debugging, do nothing if already off. +.El +.Sh "FILES" +.Bl -tag -width /usr/libexec/rbootd -compact +.It /dev/bpf# +packet-filter device +.It /etc/rbootd.conf +configuration file +.It /tmp/rbootd.dbg +debug output +.It /usr/mdec/rbootd +directory containing boot files +.It /var/run/rbootd.pid +process id +.El +.Sh SEE ALSO +.Xr kill 1 , +.Xr socket 2 , +.Xr signal 3 , +.Xr syslog 3 , +.Xr rmp 4 +.Sh BUGS +If multiple servers are started on the same interface, each will receive +and respond to the same boot packets. diff --git a/libexec/rbootd/rbootd.c b/libexec/rbootd/rbootd.c new file mode 100644 index 0000000..aa01583 --- /dev/null +++ b/libexec/rbootd/rbootd.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rbootd.c 8.2 (Berkeley) 2/22/94 + * + * Utah $Hdr: rbootd.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rbootd.c 8.2 (Berkeley) 2/22/94"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include "defs.h" + + +/* fd mask macros (backward compatibility with 4.2BSD) */ +#ifndef FD_SET +#ifdef notdef +typedef struct fd_set { /* this should already be in 4.2 */ + int fds_bits[1]; +} fd_set; +#endif +#define FD_ZERO(p) ((p)->fds_bits[0] = 0) +#define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n))) +#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1 << (n))) +#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n))) +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int c, fd, omask, maxfds; + fd_set rset; + + /* + * Find what name we are running under. + */ + ProgName = (ProgName = rindex(argv[0],'/')) ? ++ProgName : *argv; + + /* + * Close any open file descriptors. + * Temporarily leave stdin & stdout open for `-d', + * and stderr open for any pre-syslog error messages. + */ + { + int i, nfds = getdtablesize(); + + for (i = 0; i < nfds; i++) + if (i != fileno(stdin) && i != fileno(stdout) && + i != fileno(stderr)) + (void) close(i); + } + + /* + * Parse any arguments. + */ + while ((c = getopt(argc, argv, "adi:")) != EOF) + switch(c) { + case 'a': + BootAny++; + break; + case 'd': + DebugFlg++; + break; + case 'i': + IntfName = optarg; + break; + } + for (; optind < argc; optind++) { + if (ConfigFile == NULL) + ConfigFile = argv[optind]; + else { + fprintf(stderr, + "%s: too many config files (`%s' ignored)\n", + ProgName, argv[optind]); + } + } + + if (ConfigFile == NULL) /* use default config file */ + ConfigFile = DfltConfig; + + if (DebugFlg) { + DbgFp = stdout; /* output to stdout */ + + (void) signal(SIGUSR1, SIG_IGN); /* dont muck w/DbgFp */ + (void) signal(SIGUSR2, SIG_IGN); + } else { + (void) fclose(stdin); /* dont need these */ + (void) fclose(stdout); + + /* + * Fork off a child to do the work & exit. + */ + switch(fork()) { + case -1: /* fork failed */ + fprintf(stderr, "%s: ", ProgName); + perror("fork"); + Exit(0); + case 0: /* this is the CHILD */ + break; + default: /* this is the PARENT */ + _exit(0); + } + + /* + * Try to disassociate from the current tty. + */ + { + char *devtty = "/dev/tty"; + int i; + + if ((i = open(devtty, O_RDWR)) < 0) { + /* probably already disassociated */ + if (setpgrp(0, 0) < 0) { + fprintf(stderr, "%s: ", ProgName); + perror("setpgrp"); + } + } else { + if (ioctl(i, (u_long)TIOCNOTTY, (char *)0) < 0){ + fprintf(stderr, "%s: ", ProgName); + perror("ioctl"); + } + (void) close(i); + } + } + + (void) signal(SIGUSR1, DebugOn); + (void) signal(SIGUSR2, DebugOff); + } + + (void) fclose(stderr); /* finished with it */ + +#ifdef SYSLOG4_2 + openlog(ProgName, LOG_PID); +#else + openlog(ProgName, LOG_PID, LOG_DAEMON); +#endif + + /* + * If no interface was specified, get one now. + * + * This is convoluted because we want to get the default interface + * name for the syslog("restarted") message. If BpfGetIntfName() + * runs into an error, it will return a syslog-able error message + * (in `errmsg') which will be displayed here. + */ + if (IntfName == NULL) { + char *errmsg; + + if ((IntfName = BpfGetIntfName(&errmsg)) == NULL) { + syslog(LOG_NOTICE, "restarted (??)"); + syslog(LOG_ERR, errmsg); + Exit(0); + } + } + + syslog(LOG_NOTICE, "restarted (%s)", IntfName); + + (void) signal(SIGHUP, ReConfig); + (void) signal(SIGINT, Exit); + (void) signal(SIGTERM, Exit); + + /* + * Grab our host name and pid. + */ + if (gethostname(MyHost, MAXHOSTNAMELEN) < 0) { + syslog(LOG_ERR, "gethostname: %m"); + Exit(0); + } + MyHost[MAXHOSTNAMELEN] = '\0'; + + MyPid = getpid(); + + /* + * Write proc's pid to a file. + */ + { + FILE *fp; + + if ((fp = fopen(PidFile, "w")) != NULL) { + (void) fprintf(fp, "%d\n", MyPid); + (void) fclose(fp); + } else { + syslog(LOG_WARNING, "fopen: failed (%s)", PidFile); + } + } + + /* + * All boot files are relative to the boot directory, we might + * as well chdir() there to make life easier. + */ + if (chdir(BootDir) < 0) { + syslog(LOG_ERR, "chdir: %m (%s)", BootDir); + Exit(0); + } + + /* + * Initial configuration. + */ + omask = sigblock(sigmask(SIGHUP)); /* prevent reconfig's */ + if (GetBootFiles() == 0) /* get list of boot files */ + Exit(0); + if (ParseConfig() == 0) /* parse config file */ + Exit(0); + + /* + * Open and initialize a BPF device for the appropriate interface. + * If an error is encountered, a message is displayed and Exit() + * is called. + */ + fd = BpfOpen(); + + (void) sigsetmask(omask); /* allow reconfig's */ + + /* + * Main loop: receive a packet, determine where it came from, + * and if we service this host, call routine to handle request. + */ + maxfds = fd + 1; + FD_ZERO(&rset); + FD_SET(fd, &rset); + for (;;) { + struct timeval timeout; + fd_set r; + int nsel; + + r = rset; + + if (RmpConns == NULL) { /* timeout isnt necessary */ + nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0, + (struct timeval *)0); + } else { + timeout.tv_sec = RMP_TIMEOUT; + timeout.tv_usec = 0; + nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0, + &timeout); + } + + if (nsel < 0) { + if (errno == EINTR) + continue; + syslog(LOG_ERR, "select: %m"); + Exit(0); + } else if (nsel == 0) { /* timeout */ + DoTimeout(); /* clear stale conns */ + continue; + } + + if (FD_ISSET(fd, &r)) { + RMPCONN rconn; + CLIENT *client, *FindClient(); + int doread = 1; + + while (BpfRead(&rconn, doread)) { + doread = 0; + + if (DbgFp != NULL) /* display packet */ + DispPkt(&rconn,DIR_RCVD); + + omask = sigblock(sigmask(SIGHUP)); + + /* + * If we do not restrict service, set the + * client to NULL (ProcessPacket() handles + * this). Otherwise, check that we can + * service this host; if not, log a message + * and ignore the packet. + */ + if (BootAny) { + client = NULL; + } else if ((client=FindClient(&rconn))==NULL) { + syslog(LOG_INFO, + "%s: boot packet ignored", + EnetStr(&rconn)); + (void) sigsetmask(omask); + continue; + } + + ProcessPacket(&rconn,client); + + (void) sigsetmask(omask); + } + } + } +} + +/* +** DoTimeout -- Free any connections that have timed out. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Timed out connections in `RmpConns' will be freed. +*/ +void +DoTimeout() +{ + register RMPCONN *rtmp; + struct timeval now; + + (void) gettimeofday(&now, (struct timezone *)0); + + /* + * For each active connection, if RMP_TIMEOUT seconds have passed + * since the last packet was sent, delete the connection. + */ + for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next) + if ((rtmp->tstamp.tv_sec + RMP_TIMEOUT) < now.tv_sec) { + syslog(LOG_WARNING, "%s: connection timed out (%u)", + EnetStr(rtmp), rtmp->rmp.r_type); + RemoveConn(rtmp); + } +} + +/* +** FindClient -- Find client associated with a packet. +** +** Parameters: +** rconn - the new packet. +** +** Returns: +** Pointer to client info if found, NULL otherwise. +** +** Side Effects: +** None. +** +** Warnings: +** - This routine must be called with SIGHUP blocked since +** a reconfigure can invalidate the information returned. +*/ + +CLIENT * +FindClient(rconn) + register RMPCONN *rconn; +{ + register CLIENT *ctmp; + + for (ctmp = Clients; ctmp != NULL; ctmp = ctmp->next) + if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0], + (char *)&ctmp->addr[0], RMP_ADDRLEN) == 0) + break; + + return(ctmp); +} + +/* +** Exit -- Log an error message and exit. +** +** Parameters: +** sig - caught signal (or zero if not dying on a signal). +** +** Returns: +** Does not return. +** +** Side Effects: +** - This process ceases to exist. +*/ +void +Exit(sig) + int sig; +{ + if (sig > 0) + syslog(LOG_ERR, "going down on signal %d", sig); + else + syslog(LOG_ERR, "going down with fatal error"); + BpfClose(); + exit(1); +} + +/* +** ReConfig -- Get new list of boot files and reread config files. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - All active connections are dropped. +** - List of boot-able files is changed. +** - List of clients is changed. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +ReConfig(signo) + int signo; +{ + syslog(LOG_NOTICE, "reconfiguring boot server"); + + FreeConns(); + + if (GetBootFiles() == 0) + Exit(0); + + if (ParseConfig() == 0) + Exit(0); +} + +/* +** DebugOff -- Turn off debugging. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Debug file is closed. +*/ +void +DebugOff(signo) + int signo; +{ + if (DbgFp != NULL) + (void) fclose(DbgFp); + + DbgFp = NULL; +} + +/* +** DebugOn -- Turn on debugging. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Debug file is opened/truncated if not already opened, +** otherwise do nothing. +*/ +void +DebugOn(signo) + int signo; +{ + if (DbgFp == NULL) { + if ((DbgFp = fopen(DbgFile, "w")) == NULL) + syslog(LOG_ERR, "can't open debug file (%s)", DbgFile); + } +} diff --git a/libexec/rbootd/rmp.h b/libexec/rbootd/rmp.h new file mode 100644 index 0000000..d3b0167 --- /dev/null +++ b/libexec/rbootd/rmp.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rmp.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: rmp.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +/* + * Define MIN/MAX sizes of RMP (ethernet) packet. + * For ease of computation, the 4 octet CRC field is not included. + * + * MCLBYTES is for bpfwrite(); it is adamant about using a cluster. + */ + +#define RMP_MAX_PACKET MIN(1514,MCLBYTES) +#define RMP_MIN_PACKET 60 + +/* + * Define RMP/Ethernet Multicast address (9:0:9:0:0:4) and its length. + */ +#define RMP_ADDR { 0x9, 0x0, 0x9, 0x0, 0x0, 0x4 } +#define RMP_ADDRLEN 6 + +/* + * Define IEEE802.2 (Logical Link Control) information. + */ +#define IEEE_DSAP_HP 0xF8 /* Destination Service Access Point */ +#define IEEE_SSAP_HP 0xF8 /* Source Service Access Point */ +#define IEEE_CNTL_HP 0x0300 /* Type 1 / I format control information */ + +#define HPEXT_DXSAP 0x608 /* HP Destination Service Access Point */ +#define HPEXT_SXSAP 0x609 /* HP Source Service Access Point */ + +/* + * 802.3-style "Ethernet" header. + */ + +struct hp_hdr { + u_char daddr[RMP_ADDRLEN]; + u_char saddr[RMP_ADDRLEN]; + u_short len; +}; + +/* + * HP uses 802.2 LLC with their own local extensions. This struct makes + * sence out of this data (encapsulated in the above 802.3 packet). + */ + +struct hp_llc { + u_char dsap; /* 802.2 DSAP */ + u_char ssap; /* 802.2 SSAP */ + u_short cntrl; /* 802.2 control field */ + u_short filler; /* HP filler (must be zero) */ + u_short dxsap; /* HP extended DSAP */ + u_short sxsap; /* HP extended SSAP */ +}; diff --git a/libexec/rbootd/rmp_var.h b/libexec/rbootd/rmp_var.h new file mode 100644 index 0000000..7df1e87 --- /dev/null +++ b/libexec/rbootd/rmp_var.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rmp_var.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: rmp_var.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +/* + * Possible values for "rmp_type" fields. + */ + +#define RMP_BOOT_REQ 1 /* boot request packet */ +#define RMP_BOOT_REPL 129 /* boot reply packet */ +#define RMP_READ_REQ 2 /* read request packet */ +#define RMP_READ_REPL 130 /* read reply packet */ +#define RMP_BOOT_DONE 3 /* boot complete packet */ + +/* + * Useful constants. + */ + +#define RMP_VERSION 2 /* protocol version */ +#define RMP_TIMEOUT 600 /* timeout connection after ten minutes */ +#define RMP_PROBESID 0xffff /* session ID for probes */ +#define RMP_HOSTLEN 13 /* max length of server's name */ +#define RMP_MACHLEN 20 /* length of machine type field */ + +/* + * RMP error codes + */ + +#define RMP_E_OKAY 0 +#define RMP_E_EOF 2 /* read reply: returned end of file */ +#define RMP_E_ABORT 3 /* abort operation */ +#define RMP_E_BUSY 4 /* boot reply: server busy */ +#define RMP_E_TIMEOUT 5 /* lengthen time out (not implemented) */ +#define RMP_E_NOFILE 16 /* boot reply: file does not exist */ +#define RMP_E_OPENFILE 17 /* boot reply: file open failed */ +#define RMP_E_NODFLT 18 /* boot reply: default file does not exist */ +#define RMP_E_OPENDFLT 19 /* boot reply: default file open failed */ +#define RMP_E_BADSID 25 /* read reply: bad session ID */ +#define RMP_E_BADPACKET 27 /* Bad packet detected */ + +/* + * RMPDATALEN is the maximum number of data octets that can be stuffed + * into an RMP packet. This excludes the 802.2 LLC w/HP extensions. + */ +#define RMPDATALEN (RMP_MAX_PACKET - (sizeof(struct hp_hdr) + \ + sizeof(struct hp_llc))) + +/* + * Define sizes of packets we send. Boot and Read replies are variable + * in length depending on the length of `s'. + * + * Also, define how much space `restofpkt' can take up for outgoing + * Boot and Read replies. Boot Request packets are effectively + * limited to 255 bytes due to the preceding 1-byte length field. + */ + +#define RMPBOOTSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \ + sizeof(struct rmp_boot_repl) + s - sizeof(restofpkt)) +#define RMPREADSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \ + sizeof(struct rmp_read_repl) + s - sizeof(restofpkt) \ + - sizeof(u_char)) +#define RMPDONESIZE (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \ + sizeof(struct rmp_boot_done)) +#define RMPBOOTDATA 255 +#define RMPREADDATA (RMPDATALEN - \ + (2*sizeof(u_char)+sizeof(u_short)+sizeof(u_word))) + +/* + * This protocol defines some field sizes as "rest of ethernet packet". + * There is no easy way to specify this in C, so we use a one character + * field to denote it, and index past it to the end of the packet. + */ + +typedef char restofpkt; + +/* + * Due to the RMP packet layout, we'll run into alignment problems + * on machines that cant access words on half-word boundaries. If + * you know that your machine does not suffer from this problem, + * add it to the hp300 #define below. + * + * The following macros are used to deal with this problem: + * WORDZE(w) Return True if u_word `w' is zero, False otherwise. + * ZEROWORD(w) Set u_word `w' to zero. + * COPYWORD(w1,w2) Copy u_word `w1' to `w2'. + * GETWORD(w,i) Copy u_word `w' into int `i'. + * PUTWORD(i,w) Copy int `i' into u_word `w'. + * + * N.B. We do not support little endian alignment-challenged machines. + */ +#if defined(vax) || defined(tahoe) || defined(hp300) + +typedef u_int u_word; + +#define WORDZE(w) ((w) == 0) +#define ZEROWORD(w) (w) = 0 +#define COPYWORD(w1,w2) (w2) = (w1) +#define GETWORD(w, i) (i) = (w) +#define PUTWORD(i, w) (w) = (i) + +#else + +#define _WORD_HIGHPART 0 /* XXX: assume Big Endian for now */ +#define _WORD_LOWPART 1 + +typedef struct _uword { u_short val[2]; } u_word; + +#define WORDZE(w) \ + ((w.val[_WORD_HIGHPART] == 0) && (w.val[_WORD_LOWPART] == 0)) +#define ZEROWORD(w) \ + (w).val[_WORD_HIGHPART] = (w).val[_WORD_LOWPART] = 0 +#define COPYWORD(w1, w2) \ + { (w2).val[_WORD_HIGHPART] = (w1).val[_WORD_HIGHPART]; \ + (w2).val[_WORD_LOWPART] = (w1).val[_WORD_LOWPART]; \ + } +#define GETWORD(w, i) \ + (i) = (((u_int)(w).val[_WORD_HIGHPART]) << 16) | (w).val[_WORD_LOWPART] +#define PUTWORD(i, w) \ + { (w).val[_WORD_HIGHPART] = (u_short) (((i) >> 16) & 0xffff); \ + (w).val[_WORD_LOWPART] = (u_short) (i & 0xffff); \ + } + +#endif + +/* + * Packet structures. + */ + +struct rmp_raw { /* generic RMP packet */ + u_char rmp_type; /* packet type */ + u_char rmp_rawdata[RMPDATALEN-1]; +}; + +struct rmp_boot_req { /* boot request */ + u_char rmp_type; /* packet type (RMP_BOOT_REQ) */ + u_char rmp_retcode; /* return code (0) */ + u_word rmp_seqno; /* sequence number (real time clock) */ + u_short rmp_session; /* session id (normally 0) */ + u_short rmp_version; /* protocol version (RMP_VERSION) */ + char rmp_machtype[RMP_MACHLEN]; /* machine type */ + u_char rmp_flnmsize; /* length of rmp_flnm */ + restofpkt rmp_flnm; /* name of file to be read */ +}; + +struct rmp_boot_repl { /* boot reply */ + u_char rmp_type; /* packet type (RMP_BOOT_REPL) */ + u_char rmp_retcode; /* return code (normally 0) */ + u_word rmp_seqno; /* sequence number (from boot req) */ + u_short rmp_session; /* session id (generated) */ + u_short rmp_version; /* protocol version (RMP_VERSION) */ + u_char rmp_flnmsize; /* length of rmp_flnm */ + restofpkt rmp_flnm; /* name of file (from boot req) */ +}; + +struct rmp_read_req { /* read request */ + u_char rmp_type; /* packet type (RMP_READ_REQ) */ + u_char rmp_retcode; /* return code (0) */ + u_word rmp_offset; /* file relative byte offset */ + u_short rmp_session; /* session id (from boot repl) */ + u_short rmp_size; /* max no of bytes to send */ +}; + +struct rmp_read_repl { /* read reply */ + u_char rmp_type; /* packet type (RMP_READ_REPL) */ + u_char rmp_retcode; /* return code (normally 0) */ + u_word rmp_offset; /* byte offset (from read req) */ + u_short rmp_session; /* session id (from read req) */ + restofpkt rmp_data; /* data (max size from read req) */ + u_char rmp_unused; /* padding to 16-bit boundary */ +}; + +struct rmp_boot_done { /* boot complete */ + u_char rmp_type; /* packet type (RMP_BOOT_DONE) */ + u_char rmp_retcode; /* return code (0) */ + u_word rmp_unused; /* not used (0) */ + u_short rmp_session; /* session id (from read repl) */ +}; + +struct rmp_packet { + struct hp_hdr hp_hdr; + struct hp_llc hp_llc; + union { + struct rmp_boot_req rmp_brq; /* boot request */ + struct rmp_boot_repl rmp_brpl; /* boot reply */ + struct rmp_read_req rmp_rrq; /* read request */ + struct rmp_read_repl rmp_rrpl; /* read reply */ + struct rmp_boot_done rmp_done; /* boot complete */ + struct rmp_raw rmp_raw; /* raw data */ + } rmp_proto; +}; + +/* + * Make life easier... + */ + +#define r_type rmp_proto.rmp_raw.rmp_type +#define r_data rmp_proto.rmp_raw.rmp_data +#define r_brq rmp_proto.rmp_brq +#define r_brpl rmp_proto.rmp_brpl +#define r_rrq rmp_proto.rmp_rrq +#define r_rrpl rmp_proto.rmp_rrpl +#define r_done rmp_proto.rmp_done diff --git a/libexec/rbootd/rmpproto.c b/libexec/rbootd/rmpproto.c new file mode 100644 index 0000000..d0a8d4a --- /dev/null +++ b/libexec/rbootd/rmpproto.c @@ -0,0 +1,593 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rmpproto.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: rmpproto.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/time.h> + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <syslog.h> +#include <unistd.h> +#include "defs.h" + +/* +** ProcessPacket -- determine packet type and do what's required. +** +** An RMP BOOT packet has been received. Look at the type field +** and process Boot Requests, Read Requests, and Boot Complete +** packets. Any other type will be dropped with a warning msg. +** +** Parameters: +** rconn - the new connection +** client - list of files available to this host +** +** Returns: +** Nothing. +** +** Side Effects: +** - If this is a valid boot request, it will be added to +** the linked list of outstanding requests (RmpConns). +** - If this is a valid boot complete, its associated +** entry in RmpConns will be deleted. +** - Also, unless we run out of memory, a reply will be +** sent to the host that sent the packet. +*/ +void +ProcessPacket(rconn, client) + RMPCONN *rconn; + CLIENT *client; +{ + struct rmp_packet *rmp; + RMPCONN *rconnout; + + rmp = &rconn->rmp; /* cache pointer to RMP packet */ + + switch(rmp->r_type) { /* do what we came here to do */ + case RMP_BOOT_REQ: /* boot request */ + if ((rconnout = NewConn(rconn)) == NULL) + return; + + /* + * If the Session ID is 0xffff, this is a "probe" + * packet and we do not want to add the connection + * to the linked list of active connections. There + * are two types of probe packets, if the Sequence + * Number is 0 they want to know our host name, o/w + * they want the name of the file associated with + * the number spec'd by the Sequence Number. + * + * If this is an actual boot request, open the file + * and send a reply. If SendBootRepl() does not + * return 0, add the connection to the linked list + * of active connections, otherwise delete it since + * an error was encountered. + */ + if (rmp->r_brq.rmp_session == RMP_PROBESID) { + if (WORDZE(rmp->r_brq.rmp_seqno)) + (void) SendServerID(rconnout); + else + (void) SendFileNo(rmp, rconnout, + client? client->files: + BootFiles); + FreeConn(rconnout); + } else { + if (SendBootRepl(rmp, rconnout, + client? client->files: BootFiles)) + AddConn(rconnout); + else + FreeConn(rconnout); + } + break; + + case RMP_BOOT_REPL: /* boot reply (not valid) */ + syslog(LOG_WARNING, "%s: sent a boot reply", + EnetStr(rconn)); + break; + + case RMP_READ_REQ: /* read request */ + /* + * Send a portion of the boot file. + */ + (void) SendReadRepl(rconn); + break; + + case RMP_READ_REPL: /* read reply (not valid) */ + syslog(LOG_WARNING, "%s: sent a read reply", + EnetStr(rconn)); + break; + + case RMP_BOOT_DONE: /* boot complete */ + /* + * Remove the entry from the linked list of active + * connections. + */ + (void) BootDone(rconn); + break; + + default: /* unknown RMP packet type */ + syslog(LOG_WARNING, "%s: unknown packet type (%u)", + EnetStr(rconn), rmp->r_type); + } +} + +/* +** SendServerID -- send our host name to who ever requested it. +** +** Parameters: +** rconn - the reply packet to be formatted. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendServerID(rconn) + RMPCONN *rconn; +{ + register struct rmp_packet *rpl; + register char *src, *dst; + register u_char *size; + + rpl = &rconn->rmp; /* cache ptr to RMP packet */ + + /* + * Set up assorted fields in reply packet. + */ + rpl->r_brpl.rmp_type = RMP_BOOT_REPL; + rpl->r_brpl.rmp_retcode = RMP_E_OKAY; + ZEROWORD(rpl->r_brpl.rmp_seqno); + rpl->r_brpl.rmp_session = 0; + rpl->r_brpl.rmp_version = RMP_VERSION; + + size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */ + + /* + * Copy our host name into the reply packet incrementing the + * length as we go. Stop at RMP_HOSTLEN or the first dot. + */ + src = MyHost; + dst = (char *) &rpl->r_brpl.rmp_flnm; + for (*size = 0; *size < RMP_HOSTLEN; (*size)++) { + if (*src == '.' || *src == '\0') + break; + *dst++ = *src++; + } + + rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ + + return(SendPacket(rconn)); /* send packet */ +} + +/* +** SendFileNo -- send the name of a bootable file to the requester. +** +** Parameters: +** req - RMP BOOT packet containing the request. +** rconn - the reply packet to be formatted. +** filelist - list of files available to the requester. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendFileNo(req, rconn, filelist) + struct rmp_packet *req; + RMPCONN *rconn; + char *filelist[]; +{ + register struct rmp_packet *rpl; + register char *src, *dst; + register u_char *size, i; + + GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */ + rpl = &rconn->rmp; /* cache ptr to RMP packet */ + + /* + * Set up assorted fields in reply packet. + */ + rpl->r_brpl.rmp_type = RMP_BOOT_REPL; + PUTWORD(i, rpl->r_brpl.rmp_seqno); + i--; + rpl->r_brpl.rmp_session = 0; + rpl->r_brpl.rmp_version = RMP_VERSION; + + size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */ + *size = 0; /* init length to zero */ + + /* + * Copy the file name into the reply packet incrementing the + * length as we go. Stop at end of string or when RMPBOOTDATA + * characters have been copied. Also, set return code to + * indicate success or "no more files". + */ + if (i < C_MAXFILE && filelist[i] != NULL) { + src = filelist[i]; + dst = (char *)&rpl->r_brpl.rmp_flnm; + for (; *src && *size < RMPBOOTDATA; (*size)++) { + if (*src == '\0') + break; + *dst++ = *src++; + } + rpl->r_brpl.rmp_retcode = RMP_E_OKAY; + } else + rpl->r_brpl.rmp_retcode = RMP_E_NODFLT; + + rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ + + return(SendPacket(rconn)); /* send packet */ +} + +/* +** SendBootRepl -- open boot file and respond to boot request. +** +** Parameters: +** req - RMP BOOT packet containing the request. +** rconn - the reply packet to be formatted. +** filelist - list of files available to the requester. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendBootRepl(req, rconn, filelist) + struct rmp_packet *req; + RMPCONN *rconn; + char *filelist[]; +{ + int retval; + char *filename, filepath[RMPBOOTDATA+1]; + RMPCONN *oldconn; + register struct rmp_packet *rpl; + register char *src, *dst1, *dst2; + register u_char i; + + /* + * If another connection already exists, delete it since we + * are obviously starting again. + */ + if ((oldconn = FindConn(rconn)) != NULL) { + syslog(LOG_WARNING, "%s: dropping existing connection", + EnetStr(oldconn)); + RemoveConn(oldconn); + } + + rpl = &rconn->rmp; /* cache ptr to RMP packet */ + + /* + * Set up assorted fields in reply packet. + */ + rpl->r_brpl.rmp_type = RMP_BOOT_REPL; + COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno); + rpl->r_brpl.rmp_session = GenSessID(); + rpl->r_brpl.rmp_version = RMP_VERSION; + rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize; + + /* + * Copy file name to `filepath' string, and into reply packet. + */ + src = &req->r_brq.rmp_flnm; + dst1 = filepath; + dst2 = &rpl->r_brpl.rmp_flnm; + for (i = 0; i < req->r_brq.rmp_flnmsize; i++) + *dst1++ = *dst2++ = *src++; + *dst1 = '\0'; + + /* + * If we are booting HP-UX machines, their secondary loader will + * ask for files like "/hp-ux". As a security measure, we do not + * allow boot files to lay outside the boot directory (unless they + * are purposely link'd out. So, make `filename' become the path- + * stripped file name and spoof the client into thinking that it + * really got what it wanted. + */ + filename = (filename = rindex(filepath,'/'))? ++filename: filepath; + + /* + * Check that this is a valid boot file name. + */ + for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++) + if (STREQN(filename, filelist[i])) + goto match; + + /* + * Invalid boot file name, set error and send reply packet. + */ + rpl->r_brpl.rmp_retcode = RMP_E_NOFILE; + retval = 0; + goto sendpkt; + +match: + /* + * This is a valid boot file. Open the file and save the file + * descriptor associated with this connection and set success + * indication. If the file couldnt be opened, set error: + * "no such file or dir" - RMP_E_NOFILE + * "file table overflow" - RMP_E_BUSY + * "too many open files" - RMP_E_BUSY + * anything else - RMP_E_OPENFILE + */ + if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) { + rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE: + (errno == EMFILE || errno == ENFILE)? RMP_E_BUSY: + RMP_E_OPENFILE; + retval = 0; + } else { + rpl->r_brpl.rmp_retcode = RMP_E_OKAY; + retval = 1; + } + +sendpkt: + syslog(LOG_INFO, "%s: request to boot %s (%s)", + EnetStr(rconn), filename, retval? "granted": "denied"); + + rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize); + + return (retval & SendPacket(rconn)); +} + +/* +** SendReadRepl -- send a portion of the boot file to the requester. +** +** Parameters: +** rconn - the reply packet to be formatted. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendReadRepl(rconn) + RMPCONN *rconn; +{ + int retval; + RMPCONN *oldconn; + register struct rmp_packet *rpl, *req; + register int size = 0; + int madeconn = 0; + + /* + * Find the old connection. If one doesnt exist, create one only + * to return the error code. + */ + if ((oldconn = FindConn(rconn)) == NULL) { + if ((oldconn = NewConn(rconn)) == NULL) + return(0); + syslog(LOG_ERR, "SendReadRepl: no active connection (%s)", + EnetStr(rconn)); + madeconn++; + } + + req = &rconn->rmp; /* cache ptr to request packet */ + rpl = &oldconn->rmp; /* cache ptr to reply packet */ + + if (madeconn) { /* no active connection above; abort */ + rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; + retval = 1; + goto sendpkt; + } + + /* + * Make sure Session ID's match. + */ + if (req->r_rrq.rmp_session != + ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session: + rpl->r_rrpl.rmp_session)) { + syslog(LOG_ERR, "SendReadRepl: bad session id (%s)", + EnetStr(rconn)); + rpl->r_rrpl.rmp_retcode = RMP_E_BADSID; + retval = 1; + goto sendpkt; + } + + /* + * If the requester asks for more data than we can fit, + * silently clamp the request size down to RMPREADDATA. + * + * N.B. I do not know if this is "legal", however it seems + * to work. This is necessary for bpfwrite() on machines + * with MCLBYTES less than 1514. + */ + if (req->r_rrq.rmp_size > RMPREADDATA) + req->r_rrq.rmp_size = RMPREADDATA; + + /* + * Position read head on file according to info in request packet. + */ + GETWORD(req->r_rrq.rmp_offset, size); + if (lseek(oldconn->bootfd, (off_t)size, L_SET) < 0) { + syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)", + EnetStr(rconn)); + rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; + retval = 1; + goto sendpkt; + } + + /* + * Read data directly into reply packet. + */ + if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data, + (int) req->r_rrq.rmp_size)) <= 0) { + if (size < 0) { + syslog(LOG_ERR, "SendReadRepl: read: %m (%s)", + EnetStr(rconn)); + rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; + } else { + rpl->r_rrpl.rmp_retcode = RMP_E_EOF; + } + retval = 1; + goto sendpkt; + } + + /* + * Set success indication. + */ + rpl->r_rrpl.rmp_retcode = RMP_E_OKAY; + +sendpkt: + /* + * Set up assorted fields in reply packet. + */ + rpl->r_rrpl.rmp_type = RMP_READ_REPL; + COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset); + rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session; + + oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */ + + retval &= SendPacket(oldconn); /* send packet */ + + if (madeconn) /* clean up after ourself */ + FreeConn(oldconn); + + return (retval); +} + +/* +** BootDone -- free up memory allocated for a connection. +** +** Parameters: +** rconn - incoming boot complete packet. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +BootDone(rconn) + RMPCONN *rconn; +{ + RMPCONN *oldconn; + struct rmp_packet *rpl; + + /* + * If we cant find the connection, ignore the request. + */ + if ((oldconn = FindConn(rconn)) == NULL) { + syslog(LOG_ERR, "BootDone: no existing connection (%s)", + EnetStr(rconn)); + return(0); + } + + rpl = &oldconn->rmp; /* cache ptr to RMP packet */ + + /* + * Make sure Session ID's match. + */ + if (rconn->rmp.r_rrq.rmp_session != + ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session: + rpl->r_rrpl.rmp_session)) { + syslog(LOG_ERR, "BootDone: bad session id (%s)", + EnetStr(rconn)); + return(0); + } + + RemoveConn(oldconn); /* remove connection */ + + syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn)); + + return(1); +} + +/* +** SendPacket -- send an RMP packet to a remote host. +** +** Parameters: +** rconn - packet to be sent. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendPacket(rconn) + register RMPCONN *rconn; +{ + /* + * Set Ethernet Destination address to Source (BPF and the enet + * driver will take care of getting our source address set). + */ + bcopy((char *)&rconn->rmp.hp_hdr.saddr[0], + (char *)&rconn->rmp.hp_hdr.daddr[0], RMP_ADDRLEN); + rconn->rmp.hp_hdr.len = rconn->rmplen - sizeof(struct hp_hdr); + + /* + * Reverse 802.2/HP Extended Source & Destination Access Pts. + */ + rconn->rmp.hp_llc.dxsap = HPEXT_SXSAP; + rconn->rmp.hp_llc.sxsap = HPEXT_DXSAP; + + /* + * Last time this connection was active. + */ + (void) gettimeofday(&rconn->tstamp, (struct timezone *)0); + + if (DbgFp != NULL) /* display packet */ + DispPkt(rconn,DIR_SENT); + + /* + * Send RMP packet to remote host. + */ + return(BpfWrite(rconn)); +} diff --git a/libexec/rbootd/utils.c b/libexec/rbootd/utils.c new file mode 100644 index 0000000..58ead7c --- /dev/null +++ b/libexec/rbootd/utils.c @@ -0,0 +1,557 @@ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)utils.c 8.2 (Berkeley) 2/22/94 + * + * Utah $Hdr: utils.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)utils.c 8.2 (Berkeley) 2/22/94"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/time.h> + +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> +#include "defs.h" + +/* +** DispPkt -- Display the contents of an RMPCONN packet. +** +** Parameters: +** rconn - packet to be displayed. +** direct - direction packet is going (DIR_*). +** +** Returns: +** Nothing. +** +** Side Effects: +** None. +*/ +void +DispPkt(rconn, direct) + RMPCONN *rconn; + int direct; +{ + static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u"; + static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n"; + + struct tm *tmp; + register struct rmp_packet *rmp; + int i, omask; + u_int t; + + /* + * Since we will be working with RmpConns as well as DbgFp, we + * must block signals that can affect either. + */ + omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2)); + + if (DbgFp == NULL) { /* sanity */ + (void) sigsetmask(omask); + return; + } + + /* display direction packet is going using '>>>' or '<<<' */ + fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp); + + /* display packet timestamp */ + tmp = localtime((time_t *)&rconn->tstamp.tv_sec); + fprintf(DbgFp, "%02d:%02d:%02d.%06ld ", tmp->tm_hour, tmp->tm_min, + tmp->tm_sec, rconn->tstamp.tv_usec); + + /* display src or dst addr and information about network interface */ + fprintf(DbgFp, "Addr: %s Intf: %s\n", EnetStr(rconn), IntfName); + + rmp = &rconn->rmp; + + /* display IEEE 802.2 Logical Link Control header */ + (void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n", + rmp->hp_llc.dsap, rmp->hp_llc.ssap, rmp->hp_llc.cntrl); + + /* display HP extensions to 802.2 Logical Link Control header */ + (void) fprintf(DbgFp, "\tHP Ext: DXSAP:%x SXSAP:%x\n", + rmp->hp_llc.dxsap, rmp->hp_llc.sxsap); + + /* + * Display information about RMP packet using type field to + * determine what kind of packet this is. + */ + switch(rmp->r_type) { + case RMP_BOOT_REQ: /* boot request */ + (void) fprintf(DbgFp, "\tBoot Request:"); + GETWORD(rmp->r_brq.rmp_seqno, t); + if (rmp->r_brq.rmp_session == RMP_PROBESID) { + if (WORDZE(rmp->r_brq.rmp_seqno)) + fputs(" (Send Server ID)", DbgFp); + else + fprintf(DbgFp," (Send Filename #%u)",t); + } + (void) fputc('\n', DbgFp); + (void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode, + t, rmp->r_brq.rmp_session, + rmp->r_brq.rmp_version); + (void) fprintf(DbgFp, "\n\t\tMachine Type: "); + for (i = 0; i < RMP_MACHLEN; i++) + (void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp); + DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm); + break; + case RMP_BOOT_REPL: /* boot reply */ + fprintf(DbgFp, "\tBoot Reply:\n"); + GETWORD(rmp->r_brpl.rmp_seqno, t); + (void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode, + t, rmp->r_brpl.rmp_session, + rmp->r_brpl.rmp_version); + DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm); + break; + case RMP_READ_REQ: /* read request */ + (void) fprintf(DbgFp, "\tRead Request:\n"); + GETWORD(rmp->r_rrq.rmp_offset, t); + (void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode, + t, rmp->r_rrq.rmp_session); + (void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n", + rmp->r_rrq.rmp_size); + break; + case RMP_READ_REPL: /* read reply */ + (void) fprintf(DbgFp, "\tRead Reply:\n"); + GETWORD(rmp->r_rrpl.rmp_offset, t); + (void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode, + t, rmp->r_rrpl.rmp_session); + (void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n", + rconn->rmplen - RMPREADSIZE(0)); + break; + case RMP_BOOT_DONE: /* boot complete */ + (void) fprintf(DbgFp, "\tBoot Complete:\n"); + (void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n", + rmp->r_done.rmp_retcode, + rmp->r_done.rmp_session); + break; + default: /* ??? */ + (void) fprintf(DbgFp, "\tUnknown Type:(%d)\n", + rmp->r_type); + } + (void) fputc('\n', DbgFp); + (void) fflush(DbgFp); + + (void) sigsetmask(omask); /* reset old signal mask */ +} + + +/* +** GetEtherAddr -- convert an RMP (Ethernet) address into a string. +** +** An RMP BOOT packet has been received. Look at the type field +** and process Boot Requests, Read Requests, and Boot Complete +** packets. Any other type will be dropped with a warning msg. +** +** Parameters: +** addr - array of RMP_ADDRLEN bytes. +** +** Returns: +** Pointer to static string representation of `addr'. +** +** Side Effects: +** None. +** +** Warnings: +** - The return value points to a static buffer; it must +** be copied if it's to be saved. +** - For speed, we assume a u_char consists of 8 bits. +*/ +char * +GetEtherAddr(addr) + u_char *addr; +{ + static char Hex[] = "0123456789abcdef"; + static char etherstr[RMP_ADDRLEN*3]; + register int i; + register char *cp1, *cp2; + + /* + * For each byte in `addr', convert it to "<hexchar><hexchar>:". + * The last byte does not get a trailing `:' appended. + */ + i = 0; + cp1 = (char *)addr; + cp2 = etherstr; + for(;;) { + *cp2++ = Hex[*cp1 >> 4 & 0xf]; + *cp2++ = Hex[*cp1++ & 0xf]; + if (++i == RMP_ADDRLEN) + break; + *cp2++ = ':'; + } + *cp2 = '\0'; + + return(etherstr); +} + + +/* +** DispFlnm -- Print a string of bytes to DbgFp (often, a file name). +** +** Parameters: +** size - number of bytes to print. +** flnm - address of first byte. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Characters are sent to `DbgFp'. +*/ +void +DspFlnm(size, flnm) + register u_int size; + register char *flnm; +{ + register int i; + + (void) fprintf(DbgFp, "\n\t\tFile Name (%d): <", size); + for (i = 0; i < size; i++) + (void) fputc(*flnm++, DbgFp); + (void) fputs(">\n", DbgFp); +} + + +/* +** NewClient -- allocate memory for a new CLIENT. +** +** Parameters: +** addr - RMP (Ethernet) address of new client. +** +** Returns: +** Ptr to new CLIENT or NULL if we ran out of memory. +** +** Side Effects: +** - Memory will be malloc'd for the new CLIENT. +** - If malloc() fails, a log message will be generated. +*/ +CLIENT * +NewClient(addr) + u_char *addr; +{ + CLIENT *ctmp; + + if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) { + syslog(LOG_ERR, "NewClient: out of memory (%s)", + GetEtherAddr(addr)); + return(NULL); + } + + bzero(ctmp, sizeof(CLIENT)); + bcopy(addr, &ctmp->addr[0], RMP_ADDRLEN); + return(ctmp); +} + +/* +** FreeClient -- free linked list of Clients. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - All malloc'd memory associated with the linked list of +** CLIENTS will be free'd; `Clients' will be set to NULL. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +FreeClients() +{ + register CLIENT *ctmp; + + while (Clients != NULL) { + ctmp = Clients; + Clients = Clients->next; + FreeClient(ctmp); + } +} + +/* +** NewStr -- allocate memory for a character array. +** +** Parameters: +** str - null terminated character array. +** +** Returns: +** Ptr to new character array or NULL if we ran out of memory. +** +** Side Effects: +** - Memory will be malloc'd for the new character array. +** - If malloc() fails, a log message will be generated. +*/ +char * +NewStr(str) + char *str; +{ + char *stmp; + + if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) { + syslog(LOG_ERR, "NewStr: out of memory (%s)", str); + return(NULL); + } + + (void) strcpy(stmp, str); + return(stmp); +} + +/* +** To save time, NewConn and FreeConn maintain a cache of one RMPCONN +** in `LastFree' (defined below). +*/ + +static RMPCONN *LastFree = NULL; + +/* +** NewConn -- allocate memory for a new RMPCONN connection. +** +** Parameters: +** rconn - initialization template for new connection. +** +** Returns: +** Ptr to new RMPCONN or NULL if we ran out of memory. +** +** Side Effects: +** - Memory may be malloc'd for the new RMPCONN (if not cached). +** - If malloc() fails, a log message will be generated. +*/ +RMPCONN * +NewConn(rconn) + RMPCONN *rconn; +{ + RMPCONN *rtmp; + + if (LastFree == NULL) { /* nothing cached; make a new one */ + if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) { + syslog(LOG_ERR, "NewConn: out of memory (%s)", + EnetStr(rconn)); + return(NULL); + } + } else { /* use the cached RMPCONN */ + rtmp = LastFree; + LastFree = NULL; + } + + /* + * Copy template into `rtmp', init file descriptor to `-1' and + * set ptr to next elem NULL. + */ + bcopy((char *)rconn, (char *)rtmp, sizeof(RMPCONN)); + rtmp->bootfd = -1; + rtmp->next = NULL; + + return(rtmp); +} + +/* +** FreeConn -- Free memory associated with an RMPCONN connection. +** +** Parameters: +** rtmp - ptr to RMPCONN to be free'd. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Memory associated with `rtmp' may be free'd (or cached). +** - File desc associated with `rtmp->bootfd' will be closed. +*/ +void +FreeConn(rtmp) + register RMPCONN *rtmp; +{ + /* + * If the file descriptor is in use, close the file. + */ + if (rtmp->bootfd >= 0) { + (void) close(rtmp->bootfd); + rtmp->bootfd = -1; + } + + if (LastFree == NULL) /* cache for next time */ + rtmp = LastFree; + else /* already one cached; free this one */ + free((char *)rtmp); +} + +/* +** FreeConns -- free linked list of RMPCONN connections. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - All malloc'd memory associated with the linked list of +** connections will be free'd; `RmpConns' will be set to NULL. +** - If LastFree is != NULL, it too will be free'd & NULL'd. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +FreeConns() +{ + register RMPCONN *rtmp; + + while (RmpConns != NULL) { + rtmp = RmpConns; + RmpConns = RmpConns->next; + FreeConn(rtmp); + } + + if (LastFree != NULL) { + free((char *)LastFree); + LastFree = NULL; + } +} + +/* +** AddConn -- Add a connection to the linked list of connections. +** +** Parameters: +** rconn - connection to be added. +** +** Returns: +** Nothing. +** +** Side Effects: +** - RmpConn will point to new connection. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +AddConn(rconn) + register RMPCONN *rconn; +{ + if (RmpConns != NULL) + rconn->next = RmpConns; + RmpConns = rconn; +} + +/* +** FindConn -- Find a connection in the linked list of connections. +** +** We use the RMP (Ethernet) address as the basis for determining +** if this is the same connection. According to the Remote Maint +** Protocol, we can only have one connection with any machine. +** +** Parameters: +** rconn - connection to be found. +** +** Returns: +** Matching connection from linked list or NULL if not found. +** +** Side Effects: +** None. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +RMPCONN * +FindConn(rconn) + register RMPCONN *rconn; +{ + register RMPCONN *rtmp; + + for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next) + if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0], + (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0) + break; + + return(rtmp); +} + +/* +** RemoveConn -- Remove a connection from the linked list of connections. +** +** Parameters: +** rconn - connection to be removed. +** +** Returns: +** Nothing. +** +** Side Effects: +** - If found, an RMPCONN will cease to exist and it will +** be removed from the linked list. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +RemoveConn(rconn) + register RMPCONN *rconn; +{ + register RMPCONN *thisrconn, *lastrconn; + + if (RmpConns == rconn) { /* easy case */ + RmpConns = RmpConns->next; + FreeConn(rconn); + } else { /* must traverse linked list */ + lastrconn = RmpConns; /* set back ptr */ + thisrconn = lastrconn->next; /* set current ptr */ + while (thisrconn != NULL) { + if (rconn == thisrconn) { /* found it */ + lastrconn->next = thisrconn->next; + FreeConn(thisrconn); + break; + } + lastrconn = thisrconn; + thisrconn = thisrconn->next; + } + } +} |