diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 1997-08-11 13:08:30 +0000 |
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 1997-08-11 13:08:30 +0000 |
| commit | 3ab8ee7cc4a96eab986e46bb079a51ffa7155dbc (patch) | |
| tree | 8a35c89965fedc4b13c96c0e907166eb9db2d71b | |
| parent | 1114e11649f79100abc3433772522a53f09ea8f3 (diff) | |
Notes
36 files changed, 8398 insertions, 0 deletions
diff --git a/bin/date/vary.c b/bin/date/vary.c new file mode 100644 index 000000000000..be9f76240e38 --- /dev/null +++ b/bin/date/vary.c @@ -0,0 +1,384 @@ +#include <time.h> +#include <string.h> +#include <stdlib.h> +#include "vary.h" + +struct trans { + int val; + char *str; +}; + +static struct trans trans_mon[] = { + { 1, "january" }, { 2, "february" }, { 3, "march" }, { 4, "april" }, + { 6, "june" }, { 7, "july" }, { 8, "august" }, { 9, "september" }, + { 10, "october" }, { 11, "november" }, { 12, "december" }, + { -1, NULL } +}; + +static struct trans trans_wday[] = { + { 0, "sunday" }, { 1, "monday" }, { 2, "tuesday" }, { 3, "wednesday" }, + { 4, "thursday" }, { 5, "friday" }, { 6, "saturday" }, + { -1, NULL } +}; + +static char digits[] = "0123456789"; + +static int +trans(const struct trans t[], const char *arg) +{ + int f; + + for (f = 0; t[f].val != -1; f++) + if (!strncasecmp(t[f].str, arg, 3) || + !strncasecmp(t[f].str, arg, strlen(t[f].str))) + return t[f].val; + + return -1; +} + +struct vary * +vary_append(struct vary *v, char *arg) +{ + struct vary *result, **nextp; + + if (v) { + result = v; + while (v->next) + v = v->next; + nextp = &v->next; + } else + nextp = &result; + + *nextp = (struct vary *)malloc(sizeof(struct vary)); + (*nextp)->arg = arg; + (*nextp)->next = NULL; + return result; +} + +static int mdays[12] = { 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static int +daysinmonth(const struct tm *t) +{ + int year; + + year = t->tm_year + 1900; + + if (t->tm_mon == 1) + if (!(year % 400)) + return 29; + else if (!(year % 100)) + return 28; + else if (!(year % 4)) + return 29; + else + return 28; + else if (t->tm_mon >= 0 && t->tm_mon < 12) + return mdays[t->tm_mon]; + + return 0; +} + + +static int +adjyear(struct tm *t, char type, int val) +{ + switch (type) { + case '+': + t->tm_year += val; + break; + case '-': + t->tm_year -= val; + break; + default: + t->tm_year = val; + if (t->tm_year < 69) + t->tm_year += 100; /* as per date.c */ + else if (t->tm_year > 1900) + t->tm_year -= 1900; /* struct tm holds years since 1900 */ + break; + } + return mktime(t) != -1; +} + +static int +adjmon(struct tm *t, char type, int val, int istext) +{ + if (val < 0) + return 0; + + switch (type) { + case '+': + if (istext) + if (val <= t->tm_mon) + val += 11 - t->tm_mon; /* early next year */ + else + val -= t->tm_mon + 1; /* later this year */ + if (!adjyear(t, '+', (t->tm_mon + val) / 12)) + return 0; + val %= 12; + t->tm_mon += val; + if (t->tm_mon > 11) + t->tm_mon -= 12; + break; + + case '-': + if (istext) + if (val-1 > t->tm_mon) + val = 13 - val + t->tm_mon; /* later last year */ + else + val = t->tm_mon - val + 1; /* early this year */ + if (!adjyear(t, '-', val / 12)) + return 0; + val %= 12; + if (val > t->tm_mon) { + if (!adjyear(t, '-', 1)) + return 0; + val -= 12; + } + t->tm_mon -= val; + break; + + default: + if (val > 12 || val < 1) + return 0; + t->tm_mon = --val; + } + + return mktime(t) != -1; +} + +static int +adjday(struct tm *t, char type, int val) +{ + int mdays; + switch (type) { + case '+': + while (val) { + mdays = daysinmonth(t); + if (val > mdays - t->tm_mday) { + val -= mdays - t->tm_mday + 1; + t->tm_mday = 1; + if (!adjmon(t, '+', 1, 0)) + return 0; + } else { + t->tm_mday += val; + val = 0; + } + } + break; + case '-': + while (val) + if (val >= t->tm_mday) { + val -= t->tm_mday; + t->tm_mday = 1; + if (!adjmon(t, '-', 1, 0)) + return 0; + t->tm_mday = daysinmonth(t); + } else { + t->tm_mday -= val; + val = 0; + } + break; + default: + if (val > 0 && val <= daysinmonth(t)) + t->tm_mday = val; + else + return 0; + break; + } + + return mktime(t) != -1; +} + +static int +adjwday(struct tm *t, char type, int val, int istext) +{ + if (val < 0) + return 0; + + switch (type) { + case '+': + if (istext) + if (val < t->tm_wday) + val = 7 - t->tm_wday + val; /* early next week */ + else + val -= t->tm_wday; /* later this week */ + else + val *= 7; /* "-W +5" == "5 weeks in the future" */ + return adjday(t, '+', val); + case '-': + if (istext) + if (val > t->tm_wday) + val = 7 - val + t->tm_wday; /* later last week */ + else + val = t->tm_wday - val; /* early this week */ + else + val *= 7; /* "-W -5" == "5 weeks ago" */ + return adjday(t, '-', val); + default: + if (val < t->tm_wday) + return adjday(t, '-', t->tm_wday - val); + else if (val > 6) + return 0; + else if (val > t->tm_wday) + return adjday(t, '+', val - t->tm_wday); + } + return 1; +} + +static int +adjhour(struct tm *t, char type, int val) +{ + if (val < 0) + return 0; + + switch (type) { + case '+': + if (!adjday(t, '+', (t->tm_hour + val) / 24)) + return 0; + val %= 24; + t->tm_hour += val; + if (t->tm_hour > 23) + t->tm_hour -= 24; + break; + + case '-': + if (!adjday(t, '-', val / 24)) + return 0; + val %= 24; + if (val > t->tm_hour) { + if (!adjday(t, '-', 1)) + return 0; + val -= 24; + } + t->tm_hour -= val; + break; + + default: + if (val > 23) + return 0; + t->tm_hour = val; + } + + return mktime(t) != -1; +} + +static int +adjmin(struct tm *t, char type, int val) +{ + if (val < 0) + return 0; + + switch (type) { + case '+': + if (!adjhour(t, '+', (t->tm_min + val) / 60)) + return 0; + val %= 60; + t->tm_min += val; + if (t->tm_min > 59) + t->tm_min -= 60; + break; + + case '-': + if (!adjhour(t, '-', val / 60)) + return 0; + val %= 60; + if (val > t->tm_min) { + if (!adjhour(t, '-', 1)) + return 0; + val -= 60; + } + t->tm_min -= val; + break; + + default: + if (val > 59) + return 0; + t->tm_min = val; + } + + return mktime(t) != -1; +} + +const struct vary * +vary_apply(const struct vary *v, struct tm *t) +{ + char type; + char which; + char *arg; + int len; + int val; + + for (; v; v = v->next) { + type = *v->arg; + arg = v->arg; + if (type == '+' || type == '-') + arg++; + else + type = '\0'; + len = strlen(arg); + if (len < 2) + return v; + + if (strspn(arg, digits) != len-1) { + val = trans(trans_wday, arg); + if (val != -1) { + if (!adjwday(t, type, val, 1)) + return v; + } else { + val = trans(trans_mon, arg); + if (val != -1) { + if (!adjmon(t, type, val, 1)) + return v; + } else + return v; + } + } else { + val = atoi(arg); + which = arg[len-1]; + + switch (which) { + case 'M': + if (!adjmin(t, type, val)) + return v; + break; + case 'H': + if (!adjhour(t, type, val)) + return v; + break; + case 'd': + if (!adjday(t, type, val)) + return v; + break; + case 'w': + if (!adjwday(t, type, val, 0)) + return v; + break; + case 'm': + if (!adjmon(t, type, val, 0)) + return v; + break; + case 'y': + if (!adjyear(t, type, val)) + return v; + break; + default: + return v; + } + } + } + return 0; +} + +void +vary_destroy(struct vary *v) +{ + struct vary *n; + + while (v) { + n = v->next; + free(v); + v = n; + } +} diff --git a/bin/date/vary.h b/bin/date/vary.h new file mode 100644 index 000000000000..6f54b88c4d96 --- /dev/null +++ b/bin/date/vary.h @@ -0,0 +1,8 @@ +struct vary { + char *arg; + struct vary *next; +}; + +extern struct vary *vary_append(struct vary *v, char *arg); +extern const struct vary *vary_apply(const struct vary *v, struct tm *t); +extern void vary_destroy(struct vary *v); diff --git a/contrib/cpio/copyin.c b/contrib/cpio/copyin.c new file mode 100644 index 000000000000..6f2db393f094 --- /dev/null +++ b/contrib/cpio/copyin.c @@ -0,0 +1,1377 @@ +/* copyin.c - extract or list a cpio archive + Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#if (defined(BSD) && (BSD >= 199306)) +#define HAVE_STRFTIME +#include <ctype.h> +#endif +#include "filetypes.h" +#include "system.h" +#include "cpiohdr.h" +#include "dstring.h" +#include "extern.h" +#include "defer.h" +#include "rmt.h" +#ifndef FNM_PATHNAME +#include <fnmatch.h> +#endif + +#ifndef HAVE_LCHOWN +#define lchown chown +#endif + +static void read_pattern_file (); +static void tape_skip_padding (); +static void defer_copyin (); +static void create_defered_links (); +static void create_final_defers (); + +/* Return 16-bit integer I with the bytes swapped. */ +#define swab_short(i) ((((i) << 8) & 0xff00) | (((i) >> 8) & 0x00ff)) + +/* Read the header, including the name of the file, from file + descriptor IN_DES into FILE_HDR. */ + +void +read_in_header (file_hdr, in_des) + struct new_cpio_header *file_hdr; + int in_des; +{ + long bytes_skipped = 0; /* Bytes of junk found before magic number. */ + + /* Search for a valid magic number. */ + + if (archive_format == arf_unknown) + { + char tmpbuf[512]; + int check_tar; + int peeked_bytes; + + while (archive_format == arf_unknown) + { + peeked_bytes = tape_buffered_peek (tmpbuf, in_des, 512); + if (peeked_bytes < 6) + error (1, 0, "premature end of archive"); + + if (!strncmp (tmpbuf, "070701", 6)) + archive_format = arf_newascii; + else if (!strncmp (tmpbuf, "070707", 6)) + archive_format = arf_oldascii; + else if (!strncmp (tmpbuf, "070702", 6)) + { + archive_format = arf_crcascii; + crc_i_flag = TRUE; + } + else if ((*((unsigned short *) tmpbuf) == 070707) || + (*((unsigned short *) tmpbuf) == swab_short ((unsigned short) 070707))) + archive_format = arf_binary; + else if (peeked_bytes >= 512 + && (check_tar = is_tar_header (tmpbuf))) + { + if (check_tar == 2) + archive_format = arf_ustar; + else + archive_format = arf_tar; + } + else + { + tape_buffered_read ((char *) tmpbuf, in_des, 1L); + ++bytes_skipped; + } + } + } + + if (archive_format == arf_tar || archive_format == arf_ustar) + { + if (append_flag) + last_header_start = input_bytes - io_block_size + + (in_buff - input_buffer); + if (bytes_skipped > 0) + error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped); + read_in_tar_header (file_hdr, in_des); + return; + } + + file_hdr->c_tar_linkname = NULL; + + tape_buffered_read ((char *) file_hdr, in_des, 6L); + while (1) + { + if (append_flag) + last_header_start = input_bytes - io_block_size + + (in_buff - input_buffer) - 6; + if (archive_format == arf_newascii + && !strncmp ((char *) file_hdr, "070701", 6)) + { + if (bytes_skipped > 0) + error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped); + read_in_new_ascii (file_hdr, in_des); + break; + } + if (archive_format == arf_crcascii + && !strncmp ((char *) file_hdr, "070702", 6)) + { + if (bytes_skipped > 0) + error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped); + read_in_new_ascii (file_hdr, in_des); + break; + } + if ( (archive_format == arf_oldascii || archive_format == arf_hpoldascii) + && !strncmp ((char *) file_hdr, "070707", 6)) + { + if (bytes_skipped > 0) + error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped); + read_in_old_ascii (file_hdr, in_des); + break; + } + if ( (archive_format == arf_binary || archive_format == arf_hpbinary) + && (file_hdr->c_magic == 070707 + || file_hdr->c_magic == swab_short ((unsigned short) 070707))) + { + /* Having to skip 1 byte because of word alignment is normal. */ + if (bytes_skipped > 0) + error (0, 0, "warning: skipped %ld bytes of junk", bytes_skipped); + read_in_binary (file_hdr, in_des); + break; + } + bytes_skipped++; + bcopy ((char *) file_hdr + 1, (char *) file_hdr, 5); + tape_buffered_read ((char *) file_hdr + 5, in_des, 1L); + } +} + +/* Fill in FILE_HDR by reading an old-format ASCII format cpio header from + file descriptor IN_DES, except for the magic number, which is + already filled in. */ + +void +read_in_old_ascii (file_hdr, in_des) + struct new_cpio_header *file_hdr; + int in_des; +{ + char ascii_header[78]; + unsigned long dev; + unsigned long rdev; + + tape_buffered_read (ascii_header, in_des, 70L); + ascii_header[70] = '\0'; + sscanf (ascii_header, + "%6lo%6lo%6lo%6lo%6lo%6lo%6lo%11lo%6lo%11lo", + &dev, &file_hdr->c_ino, + &file_hdr->c_mode, &file_hdr->c_uid, &file_hdr->c_gid, + &file_hdr->c_nlink, &rdev, &file_hdr->c_mtime, + &file_hdr->c_namesize, &file_hdr->c_filesize); + file_hdr->c_dev_maj = major (dev); + file_hdr->c_dev_min = minor (dev); + file_hdr->c_rdev_maj = major (rdev); + file_hdr->c_rdev_min = minor (rdev); + + /* Read file name from input. */ + if (file_hdr->c_name != NULL) + free (file_hdr->c_name); + file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize + 1); + tape_buffered_read (file_hdr->c_name, in_des, (long) file_hdr->c_namesize); +#ifndef __MSDOS__ + /* HP/UX cpio creates archives that look just like ordinary archives, + but for devices it sets major = 0, minor = 1, and puts the + actual major/minor number in the filesize field. See if this + is an HP/UX cpio archive, and if so fix it. We have to do this + here because process_copy_in() assumes filesize is always 0 + for devices. */ + switch (file_hdr->c_mode & CP_IFMT) + { + case CP_IFCHR: + case CP_IFBLK: +#ifdef CP_IFSOCK + case CP_IFSOCK: +#endif +#ifdef CP_IFIFO + case CP_IFIFO: +#endif + if (file_hdr->c_filesize != 0 + && file_hdr->c_rdev_maj == 0 + && file_hdr->c_rdev_min == 1) + { + file_hdr->c_rdev_maj = major (file_hdr->c_filesize); + file_hdr->c_rdev_min = minor (file_hdr->c_filesize); + file_hdr->c_filesize = 0; + } + break; + default: + break; + } +#endif /* __MSDOS__ */ +} + +/* Fill in FILE_HDR by reading a new-format ASCII format cpio header from + file descriptor IN_DES, except for the magic number, which is + already filled in. */ + +void +read_in_new_ascii (file_hdr, in_des) + struct new_cpio_header *file_hdr; + int in_des; +{ + char ascii_header[112]; + + tape_buffered_read (ascii_header, in_des, 104L); + ascii_header[104] = '\0'; + sscanf (ascii_header, + "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx", + &file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid, + &file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime, + &file_hdr->c_filesize, &file_hdr->c_dev_maj, &file_hdr->c_dev_min, + &file_hdr->c_rdev_maj, &file_hdr->c_rdev_min, &file_hdr->c_namesize, + &file_hdr->c_chksum); + /* Read file name from input. */ + if (file_hdr->c_name != NULL) + free (file_hdr->c_name); + file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize); + tape_buffered_read (file_hdr->c_name, in_des, (long) file_hdr->c_namesize); + + /* In SVR4 ASCII format, the amount of space allocated for the header + is rounded up to the next long-word, so we might need to drop + 1-3 bytes. */ + tape_skip_padding (in_des, file_hdr->c_namesize + 110); +} + +/* Fill in FILE_HDR by reading a binary format cpio header from + file descriptor IN_DES, except for the first 6 bytes (the magic + number, device, and inode number), which are already filled in. */ + +void +read_in_binary (file_hdr, in_des) + struct new_cpio_header *file_hdr; + int in_des; +{ + struct old_cpio_header short_hdr; + + /* Copy the data into the short header, then later transfer + it into the argument long header. */ + short_hdr.c_dev = ((struct old_cpio_header *) file_hdr)->c_dev; + short_hdr.c_ino = ((struct old_cpio_header *) file_hdr)->c_ino; + tape_buffered_read (((char *) &short_hdr) + 6, in_des, 20L); + + /* If the magic number is byte swapped, fix the header. */ + if (file_hdr->c_magic == swab_short ((unsigned short) 070707)) + { + static int warned = 0; + + /* Alert the user that they might have to do byte swapping on + the file contents. */ + if (warned == 0) + { + error (0, 0, "warning: archive header has reverse byte-order"); + warned = 1; + } + swab_array ((char *) &short_hdr, 13); + } + + file_hdr->c_dev_maj = major (short_hdr.c_dev); + file_hdr->c_dev_min = minor (short_hdr.c_dev); + file_hdr->c_ino = short_hdr.c_ino; + file_hdr->c_mode = short_hdr.c_mode; + file_hdr->c_uid = short_hdr.c_uid; + file_hdr->c_gid = short_hdr.c_gid; + file_hdr->c_nlink = short_hdr.c_nlink; + file_hdr->c_rdev_maj = major (short_hdr.c_rdev); + file_hdr->c_rdev_min = minor (short_hdr.c_rdev); + file_hdr->c_mtime = (unsigned long) short_hdr.c_mtimes[0] << 16 + | short_hdr.c_mtimes[1]; + + file_hdr->c_namesize = short_hdr.c_namesize; + file_hdr->c_filesize = (unsigned long) short_hdr.c_filesizes[0] << 16 + | short_hdr.c_filesizes[1]; + + /* Read file name from input. */ + if (file_hdr->c_name != NULL) + free (file_hdr->c_name); + file_hdr->c_name = (char *) xmalloc (file_hdr->c_namesize); + tape_buffered_read (file_hdr->c_name, in_des, (long) file_hdr->c_namesize); + + /* In binary mode, the amount of space allocated in the header for + the filename is `c_namesize' rounded up to the next short-word, + so we might need to drop a byte. */ + if (file_hdr->c_namesize % 2) + tape_toss_input (in_des, 1L); + +#ifndef __MSDOS__ + /* HP/UX cpio creates archives that look just like ordinary archives, + but for devices it sets major = 0, minor = 1, and puts the + actual major/minor number in the filesize field. See if this + is an HP/UX cpio archive, and if so fix it. We have to do this + here because process_copy_in() assumes filesize is always 0 + for devices. */ + switch (file_hdr->c_mode & CP_IFMT) + { + case CP_IFCHR: + case CP_IFBLK: +#ifdef CP_IFSOCK + case CP_IFSOCK: +#endif +#ifdef CP_IFIFO + case CP_IFIFO: +#endif + if (file_hdr->c_filesize != 0 + && file_hdr->c_rdev_maj == 0 + && file_hdr->c_rdev_min == 1) + { + file_hdr->c_rdev_maj = major (file_hdr->c_filesize); + file_hdr->c_rdev_min = minor (file_hdr->c_filesize); + file_hdr->c_filesize = 0; + } + break; + default: + break; + } +#endif /* __MSDOS__ */ +} + +/* Exchange the bytes of each element of the array of COUNT shorts + starting at PTR. */ + +void +swab_array (ptr, count) + char *ptr; + int count; +{ + char tmp; + + while (count-- > 0) + { + tmp = *ptr; + *ptr = *(ptr + 1); + ++ptr; + *ptr = tmp; + ++ptr; + } +} + +/* Current time for verbose table. */ +static time_t current_time; + +/* Read the collection from standard input and create files + in the file system. */ + +void +process_copy_in () +{ + char done = FALSE; /* True if trailer reached. */ + int res; /* Result of various function calls. */ + dynamic_string new_name; /* New file name for rename option. */ + FILE *tty_in; /* Interactive file for rename option. */ + FILE *tty_out; /* Interactive file for rename option. */ + FILE *rename_in; /* Batch file for rename option. */ + char *str_res; /* Result for string function. */ + struct utimbuf times; /* For setting file times. */ + struct stat file_stat; /* Output file stat record. */ + struct new_cpio_header file_hdr; /* Output header information. */ + int out_file_des; /* Output file descriptor. */ + int in_file_des; /* Input file descriptor. */ + char skip_file; /* Flag for use with patterns. */ + int existing_dir; /* True if file is a dir & already exists. */ + int i; /* Loop index variable. */ + char *link_name = NULL; /* Name of hard and symbolic links. */ +#ifdef HPUX_CDF + int cdf_flag; /* True if file is a CDF. */ + int cdf_char; /* Index of `+' char indicating a CDF. */ +#endif + + /* Initialize the copy in. */ + if (pattern_file_name) + read_pattern_file (); + file_hdr.c_name = NULL; + ds_init (&new_name, 128); + /* Initialize this in case it has members we don't know to set. */ + bzero (×, sizeof (struct utimbuf)); + + if (rename_batch_file) + { + rename_in = fopen (rename_batch_file, "r"); + if (rename_in == NULL) + error (2, errno, CONSOLE); + } + else if (rename_flag) + { + /* Open interactive file pair for rename operation. */ + tty_in = fopen (CONSOLE, "r"); + if (tty_in == NULL) + error (2, errno, CONSOLE); + tty_out = fopen (CONSOLE, "w"); + if (tty_out == NULL) + error (2, errno, CONSOLE); + } + + /* Get date and time if needed for processing the table option. */ + if (table_flag && verbose_flag) + time (¤t_time); + +#ifdef __MSDOS__ + setmode (archive_des, O_BINARY); +#endif + /* Check whether the input file might be a tape. */ + in_file_des = archive_des; + if (_isrmt (in_file_des)) + { + input_is_special = 1; + input_is_seekable = 0; + } + else + { + if (fstat (in_file_des, &file_stat)) + error (1, errno, "standard input is closed"); + input_is_special = +#ifdef S_ISBLK + S_ISBLK (file_stat.st_mode) || +#endif + S_ISCHR (file_stat.st_mode); + input_is_seekable = S_ISREG (file_stat.st_mode); + } + output_is_seekable = TRUE; + + /* While there is more input in the collection, process the input. */ + while (!done) + { + link_name = NULL; + swapping_halfwords = swapping_bytes = FALSE; + + /* Start processing the next file by reading the header. */ + read_in_header (&file_hdr, in_file_des); + +#ifdef DEBUG_CPIO + if (debug_flag) + { + struct new_cpio_header *h; + h = &file_hdr; + fprintf (stderr, + "magic = 0%o, ino = %d, mode = 0%o, uid = %d, gid = %d\n", + h->c_magic, h->c_ino, h->c_mode, h->c_uid, h->c_gid); + fprintf (stderr, + "nlink = %d, mtime = %d, filesize = %d, dev_maj = 0x%x\n", + h->c_nlink, h->c_mtime, h->c_filesize, h->c_dev_maj); + fprintf (stderr, + "dev_min = 0x%x, rdev_maj = 0x%x, rdev_min = 0x%x, namesize = %d\n", + h->c_dev_min, h->c_rdev_maj, h->c_rdev_min, h->c_namesize); + fprintf (stderr, + "chksum = %d, name = \"%s\", tar_linkname = \"%s\"\n", + h->c_chksum, h->c_name, + h->c_tar_linkname ? h->c_tar_linkname : "(null)" ); + + } +#endif + /* Is this the header for the TRAILER file? */ + if (strcmp ("TRAILER!!!", file_hdr.c_name) == 0) + { + done = TRUE; + break; + } + + /* Do we have to ignore absolute paths, and if so, does the filename + have an absolute path? */ + if (no_abs_paths_flag && file_hdr.c_name && file_hdr.c_name [0] == '/') + { + char *p; + + p = file_hdr.c_name; + while (*p == '/') + ++p; + if (*p == '\0') + { + strcpy (file_hdr.c_name, "."); + } + else + { + char *non_abs_name; + + non_abs_name = (char *) xmalloc (strlen (p) + 1); + strcpy (non_abs_name, p); + free (file_hdr.c_name); + file_hdr.c_name = non_abs_name; + } + } + + /* Does the file name match one of the given patterns? */ + if (num_patterns <= 0) + skip_file = FALSE; + else + { + skip_file = copy_matching_files; + for (i = 0; i < num_patterns + && skip_file == copy_matching_files; i++) + { + if (fnmatch (save_patterns[i], file_hdr.c_name, 0) == 0) + skip_file = !copy_matching_files; + } + } + + if (skip_file) + { + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + } + else if (table_flag) + { + if (verbose_flag) + { +#ifdef CP_IFLNK + if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK) + { + if (archive_format != arf_tar && archive_format != arf_ustar) + { + link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1); + link_name[file_hdr.c_filesize] = '\0'; + tape_buffered_read (link_name, in_file_des, file_hdr.c_filesize); + long_format (&file_hdr, link_name); + free (link_name); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + continue; + } + else + { + long_format (&file_hdr, file_hdr.c_tar_linkname); + continue; + } + } + else +#endif + long_format (&file_hdr, (char *) 0); + } + else + printf ("%s\n", file_hdr.c_name); + + crc = 0; + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + if (only_verify_crc_flag) + { +#ifdef CP_IFLNK + if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK) + continue; /* links don't have a checksum */ +#endif + if (crc != file_hdr.c_chksum) + error (0, 0, "%s: checksum error (0x%x, should be 0x%x)", + file_hdr.c_name, crc, file_hdr.c_chksum); + } + } + else if (append_flag) + { + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + } + else if (only_verify_crc_flag) + { +#ifdef CP_IFLNK + if ((file_hdr.c_mode & CP_IFMT) == CP_IFLNK) + { + if (archive_format != arf_tar && archive_format != arf_ustar) + { + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + continue; + } + } +#endif + crc = 0; + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + if (crc != file_hdr.c_chksum) + error (0, 0, "%s: checksum error (0x%x, should be 0x%x)", + file_hdr.c_name, crc, file_hdr.c_chksum); + } + else + { + /* Copy the input file into the directory structure. */ + + /* Do we need to rename the file? */ + if (rename_flag || rename_batch_file) + { + if (rename_flag) + { + fprintf (tty_out, "rename %s -> ", file_hdr.c_name); + fflush (tty_out); + str_res = ds_fgets (tty_in, &new_name); + } + else + { + str_res = ds_fgetstr (rename_in, &new_name, '\n'); + } + if (str_res == NULL || str_res[0] == 0) + { + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + continue; + } + else + file_hdr.c_name = xstrdup (new_name.ds_string); + } + + /* See if the file already exists. */ + existing_dir = FALSE; + if (lstat (file_hdr.c_name, &file_stat) == 0) + { + if (S_ISDIR (file_stat.st_mode) + && ((file_hdr.c_mode & CP_IFMT) == CP_IFDIR)) + { + /* If there is already a directory there that + we are trying to create, don't complain about + it. */ + existing_dir = TRUE; + } + else if (!unconditional_flag + && file_hdr.c_mtime <= file_stat.st_mtime) + { + error (0, 0, "%s not created: newer or same age version exists", + file_hdr.c_name); + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + continue; /* Go to the next file. */ + } + else if (S_ISDIR (file_stat.st_mode) + ? rmdir (file_hdr.c_name) + : unlink (file_hdr.c_name)) + { + error (0, errno, "cannot remove current %s", + file_hdr.c_name); + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + continue; /* Go to the next file. */ + } + } + + /* Do the real copy or link. */ + switch (file_hdr.c_mode & CP_IFMT) + { + case CP_IFREG: +#ifndef __MSDOS__ + /* Can the current file be linked to a previously copied file? */ + if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii + || archive_format == arf_crcascii) ) + { + int link_res; + if (file_hdr.c_filesize == 0) + { + /* The newc and crc formats store multiply linked copies + of the same file in the archive only once. The + actual data is attached to the last link in the + archive, and the other links all have a filesize + of 0. Since this file has multiple links and a + filesize of 0, its data is probably attatched to + another file in the archive. Save the link, and + process it later when we get the actual data. We + can't just create it with length 0 and add the + data later, in case the file is readonly. We still + lose if its parent directory is readonly (and we aren't + running as root), but there's nothing we can do about + that. */ + defer_copyin (&file_hdr); + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + break; + } + /* If the file has data (filesize != 0), then presumably + any other links have already been defer_copyin'ed(), + but GNU cpio version 2.0-2.2 didn't do that, so we + still have to check for links here (and also in case + the archive was created and later appeneded to). */ + link_res = link_to_maj_min_ino (file_hdr.c_name, + file_hdr.c_dev_maj, file_hdr.c_dev_maj, + file_hdr.c_ino); + if (link_res == 0) + { + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + break; + } + } + else if (file_hdr.c_nlink > 1 && archive_format != arf_tar + && archive_format != arf_ustar) + { + int link_res; + link_res = link_to_maj_min_ino (file_hdr.c_name, + file_hdr.c_dev_maj, file_hdr.c_dev_maj, + file_hdr.c_ino); + if (link_res == 0) + { + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + break; + } + } + else if ((archive_format == arf_tar || archive_format == arf_ustar) + && file_hdr.c_tar_linkname && + file_hdr.c_tar_linkname[0] != '\0') + { + int link_res; + link_res = link_to_name (file_hdr.c_name, + file_hdr.c_tar_linkname); + if (link_res < 0) + { + error (0, errno, "cannot link %s to %s", + file_hdr.c_tar_linkname, file_hdr.c_name); + } + break; + } +#endif + + /* If not linked, copy the contents of the file. */ + if (link_name == NULL) + { + out_file_des = open (file_hdr.c_name, + O_CREAT | O_WRONLY | O_BINARY, 0600); + if (out_file_des < 0 && create_dir_flag) + { + create_all_directories (file_hdr.c_name); + out_file_des = open (file_hdr.c_name, + O_CREAT | O_WRONLY | O_BINARY, + 0600); + } + if (out_file_des < 0) + { + error (0, errno, "%s", file_hdr.c_name); + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + continue; + } + + crc = 0; + if (swap_halfwords_flag) + { + if ((file_hdr.c_filesize % 4) == 0) + swapping_halfwords = TRUE; + else + error (0, 0, "cannot swap halfwords of %s: odd number of halfwords", + file_hdr.c_name); + } + if (swap_bytes_flag) + { + if ((file_hdr.c_filesize % 2) == 0) + swapping_bytes = TRUE; + else + error (0, 0, "cannot swap bytes of %s: odd number of bytes", + file_hdr.c_name); + } + copy_files_tape_to_disk (in_file_des, out_file_des, file_hdr.c_filesize); + disk_empty_output_buffer (out_file_des); + if (close (out_file_des) < 0) + error (0, errno, "%s", file_hdr.c_name); + + if (archive_format == arf_crcascii) + { + if (crc != file_hdr.c_chksum) + error (0, 0, "%s: checksum error (0x%x, should be 0x%x)", + file_hdr.c_name, crc, file_hdr.c_chksum); + } + /* File is now copied; set attributes. */ + if (!no_chown_flag) + if ((chown (file_hdr.c_name, + set_owner_flag ? set_owner : file_hdr.c_uid, + set_group_flag ? set_group : file_hdr.c_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", file_hdr.c_name); + /* chown may have turned off some permissions we wanted. */ + if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0) + error (0, errno, "%s", file_hdr.c_name); + if (retain_time_flag) + { + times.actime = times.modtime = file_hdr.c_mtime; + if (utime (file_hdr.c_name, ×) < 0) + error (0, errno, "%s", file_hdr.c_name); + } + tape_skip_padding (in_file_des, file_hdr.c_filesize); + if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii + || archive_format == arf_crcascii) ) + { + /* (see comment above for how the newc and crc formats + store multiple links). Now that we have the data + for this file, create any other links to it which + we defered. */ + create_defered_links (&file_hdr); + } + } + break; + + case CP_IFDIR: + /* Strip any trailing `/'s off the filename; tar puts + them on. We might as well do it here in case anybody + else does too, since they cause strange things to happen. */ + strip_trailing_slashes (file_hdr.c_name); + + /* Ignore the current directory. It must already exist, + and we don't want to change its permission, ownership + or time. */ + if (file_hdr.c_name[0] == '.' && file_hdr.c_name[1] == '\0') + break; + +#ifdef HPUX_CDF + cdf_flag = 0; +#endif + if (!existing_dir) + + { +#ifdef HPUX_CDF + /* If the directory name ends in a + and is SUID, + then it is a CDF. Strip the trailing + from + the name before creating it. */ + cdf_char = strlen (file_hdr.c_name) - 1; + if ( (cdf_char > 0) && + (file_hdr.c_mode & 04000) && + (file_hdr.c_name [cdf_char] == '+') ) + { + file_hdr.c_name [cdf_char] = '\0'; + cdf_flag = 1; + } +#endif + res = mkdir (file_hdr.c_name, file_hdr.c_mode); + } + else + res = 0; + if (res < 0 && create_dir_flag) + { + create_all_directories (file_hdr.c_name); + res = mkdir (file_hdr.c_name, file_hdr.c_mode); + } + if (res < 0) + { + /* In some odd cases where the file_hdr.c_name includes `.', + the directory may have actually been created by + create_all_directories(), so the mkdir will fail + because the directory exists. If that's the case, + don't complain about it. */ + if ( (errno != EEXIST) || + (lstat (file_hdr.c_name, &file_stat) != 0) || + !(S_ISDIR (file_stat.st_mode) ) ) + { + error (0, errno, "%s", file_hdr.c_name); + continue; + } + } + if (!no_chown_flag) + if ((chown (file_hdr.c_name, + set_owner_flag ? set_owner : file_hdr.c_uid, + set_group_flag ? set_group : file_hdr.c_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", file_hdr.c_name); + /* chown may have turned off some permissions we wanted. */ + if (chmod (file_hdr.c_name, (int) file_hdr.c_mode) < 0) + error (0, errno, "%s", file_hdr.c_name); +#ifdef HPUX_CDF + if (cdf_flag) + /* Once we "hide" the directory with the chmod(), + we have to refer to it using name+ instead of name. */ + file_hdr.c_name [cdf_char] = '+'; +#endif + if (retain_time_flag) + { + times.actime = times.modtime = file_hdr.c_mtime; + if (utime (file_hdr.c_name, ×) < 0) + error (0, errno, "%s", file_hdr.c_name); + } + break; + +#ifndef __MSDOS__ + case CP_IFCHR: + case CP_IFBLK: +#ifdef CP_IFSOCK + case CP_IFSOCK: +#endif +#ifdef CP_IFIFO + case CP_IFIFO: +#endif + if (file_hdr.c_nlink > 1 && archive_format != arf_tar + && archive_format != arf_ustar) + { + int link_res; + link_res = link_to_maj_min_ino (file_hdr.c_name, + file_hdr.c_dev_maj, file_hdr.c_dev_maj, + file_hdr.c_ino); + if (link_res == 0) + break; + } + else if (archive_format == arf_ustar && + file_hdr.c_tar_linkname && + file_hdr.c_tar_linkname [0] != '\0') + { + int link_res; + link_res = link_to_name (file_hdr.c_name, + file_hdr.c_tar_linkname); + if (link_res < 0) + { + error (0, errno, "cannot link %s to %s", + file_hdr.c_tar_linkname, file_hdr.c_name); + /* Something must be wrong, because we couldn't + find the file to link to. But can we assume + that the device maj/min numbers are correct + and fall through to the mknod? It's probably + safer to just break, rather than possibly + creating a bogus device file. */ + } + break; + } + +#ifdef CP_IFIFO + if ((file_hdr.c_mode & CP_IFMT) == CP_IFIFO) + res = mkfifo (file_hdr.c_name, file_hdr.c_mode); + else +#endif + res = mknod (file_hdr.c_name, file_hdr.c_mode, + makedev (file_hdr.c_rdev_maj, file_hdr.c_rdev_min)); + if (res < 0 && create_dir_flag) + { + create_all_directories (file_hdr.c_name); +#ifdef CP_IFIFO + if ((file_hdr.c_mode & CP_IFMT) == CP_IFIFO) + res = mkfifo (file_hdr.c_name, file_hdr.c_mode); + else +#endif + res = mknod (file_hdr.c_name, file_hdr.c_mode, + makedev (file_hdr.c_rdev_maj, + file_hdr.c_rdev_min)); + } + if (res < 0) + { + error (0, errno, "%s", file_hdr.c_name); + continue; + } + if (!no_chown_flag) + if ((chown (file_hdr.c_name, + set_owner_flag ? set_owner : file_hdr.c_uid, + set_group_flag ? set_group : file_hdr.c_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", file_hdr.c_name); + /* chown may have turned off some permissions we wanted. */ + if (chmod (file_hdr.c_name, file_hdr.c_mode) < 0) + error (0, errno, "%s", file_hdr.c_name); + if (retain_time_flag) + { + times.actime = times.modtime = file_hdr.c_mtime; + if (utime (file_hdr.c_name, ×) < 0) + error (0, errno, "%s", file_hdr.c_name); + } + break; +#endif + +#ifdef CP_IFLNK + case CP_IFLNK: + { + if (archive_format != arf_tar && archive_format != arf_ustar) + { + link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1); + link_name[file_hdr.c_filesize] = '\0'; + tape_buffered_read (link_name, in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + } + else + { + link_name = xstrdup (file_hdr.c_tar_linkname); + } + + res = UMASKED_SYMLINK (link_name, file_hdr.c_name, + file_hdr.c_mode); + if (res < 0 && create_dir_flag) + { + create_all_directories (file_hdr.c_name); + res = UMASKED_SYMLINK (link_name, file_hdr.c_name, + file_hdr.c_mode); + } + if (res < 0) + { + error (0, errno, "%s", file_hdr.c_name); + free (link_name); + link_name = NULL; + continue; + } + if (!no_chown_flag) + if ((lchown (file_hdr.c_name, + set_owner_flag ? set_owner : file_hdr.c_uid, + set_group_flag ? set_group : file_hdr.c_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", file_hdr.c_name); + free (link_name); + link_name = NULL; + } + break; +#endif + + default: + error (0, 0, "%s: unknown file type", file_hdr.c_name); + tape_toss_input (in_file_des, file_hdr.c_filesize); + tape_skip_padding (in_file_des, file_hdr.c_filesize); + } + + if (verbose_flag) + fprintf (stderr, "%s\n", file_hdr.c_name); + if (dot_flag) + fputc ('.', stderr); + } + } + + if (dot_flag) + fputc ('\n', stderr); + + if (append_flag) + return; + + if (archive_format == arf_newascii || archive_format == arf_crcascii) + create_final_defers (); + if (!quiet_flag) + { + res = (input_bytes + io_block_size - 1) / io_block_size; + if (res == 1) + fprintf (stderr, "1 block\n"); + else + fprintf (stderr, "%d blocks\n", res); + } +} + +/* Print the file described by FILE_HDR in long format. + If LINK_NAME is nonzero, it is the name of the file that + this file is a symbolic link to. */ + +void +long_format (file_hdr, link_name) + struct new_cpio_header *file_hdr; + char *link_name; +{ + char mbuf[11]; + char tbuf[40]; + time_t when; + + mode_string (file_hdr->c_mode, mbuf); + mbuf[10] = '\0'; + + /* Get time values ready to print. */ + when = file_hdr->c_mtime; +#ifdef HAVE_STRFTIME + strftime(tbuf, sizeof(tbuf), "%c", localtime(&when)); +#else + strcpy (tbuf, ctime (&when)); +#endif + if (current_time - when > 6L * 30L * 24L * 60L * 60L + || current_time - when < 0L) + { + /* The file is older than 6 months, or in the future. + Show the year instead of the time of day. */ + strcpy (tbuf + 11, tbuf + 19); + } + tbuf[16] = '\0'; + + printf ("%s %3u ", mbuf, file_hdr->c_nlink); + +#ifndef __MSDOS__ + if (numeric_uid) +#endif + printf ("%-8u %-8u ", (unsigned int) file_hdr->c_uid, + (unsigned int) file_hdr->c_gid); +#ifndef __MSDOS__ + else + printf ("%-8.8s %-8.8s ", getuser (file_hdr->c_uid), + getgroup (file_hdr->c_gid)); + + if ((file_hdr->c_mode & CP_IFMT) == CP_IFCHR + || (file_hdr->c_mode & CP_IFMT) == CP_IFBLK) + printf ("%3u, %3u ", file_hdr->c_rdev_maj, + file_hdr->c_rdev_min); + else +#endif + printf ("%8lu ", file_hdr->c_filesize); + + printf ("%s ", tbuf + 4); + + print_name_with_quoting (file_hdr->c_name); + if (link_name) + { + printf (" -> "); + print_name_with_quoting (link_name); + } + putc ('\n', stdout); +} + +void +print_name_with_quoting (p) + register char *p; +{ + register unsigned char c; + + while ( (c = *p++) ) + { + switch (c) + { +#ifndef __MSDOS__ + case '\\': + printf ("\\\\"); + break; +#endif + + case '\n': + printf ("\\n"); + break; + + case '\b': + printf ("\\b"); + break; + + case '\r': + printf ("\\r"); + break; + + case '\t': + printf ("\\t"); + break; + + case '\f': + printf ("\\f"); + break; + + case ' ': + printf ("\\ "); + break; + + case '"': + printf ("\\\""); + break; + + default: +#if (defined(BSD) && (BSD >= 199306)) + if (isprint(c)) +#else + if (c > 040 && +#ifdef __MSDOS__ + c < 0377 && c != 0177 +#else + c < 0177 +#endif + ) +#endif + putchar (c); + else + printf ("\\%03o", (unsigned int) c); + } + } +} + +/* Read a pattern file (for the -E option). Put a list of + `num_patterns' elements in `save_patterns'. Any patterns that were + already in `save_patterns' (from the command line) are preserved. */ + +static void +read_pattern_file () +{ + int max_new_patterns; + char **new_save_patterns; + int new_num_patterns; + int i; + dynamic_string pattern_name; + FILE *pattern_fp; + + if (num_patterns < 0) + num_patterns = 0; + max_new_patterns = 1 + num_patterns; + new_save_patterns = (char **) xmalloc (max_new_patterns * sizeof (char *)); + new_num_patterns = num_patterns; + ds_init (&pattern_name, 128); + + pattern_fp = fopen (pattern_file_name, "r"); + if (pattern_fp == NULL) + error (1, errno, "%s", pattern_file_name); + while (ds_fgetstr (pattern_fp, &pattern_name, '\n') != NULL) + { + if (new_num_patterns >= max_new_patterns) + { + max_new_patterns += 1; + new_save_patterns = (char **) + xrealloc ((char *) new_save_patterns, + max_new_patterns * sizeof (char *)); + } + new_save_patterns[new_num_patterns] = xstrdup (pattern_name.ds_string); + ++new_num_patterns; + } + if (ferror (pattern_fp) || fclose (pattern_fp) == EOF) + error (1, errno, "%s", pattern_file_name); + + for (i = 0; i < num_patterns; ++i) + new_save_patterns[i] = save_patterns[i]; + + save_patterns = new_save_patterns; + num_patterns = new_num_patterns; +} + +/* Skip the padding on IN_FILE_DES after a header or file, + up to the next header. + The number of bytes skipped is based on OFFSET -- the current offset + from the last start of a header (or file) -- and the current + header type. */ + +static void +tape_skip_padding (in_file_des, offset) + int in_file_des; + int offset; +{ + int pad; + + if (archive_format == arf_crcascii || archive_format == arf_newascii) + pad = (4 - (offset % 4)) % 4; + else if (archive_format == arf_binary || archive_format == arf_hpbinary) + pad = (2 - (offset % 2)) % 2; + else if (archive_format == arf_tar || archive_format == arf_ustar) + pad = (512 - (offset % 512)) % 512; + else + pad = 0; + + if (pad != 0) + tape_toss_input (in_file_des, pad); +} + + +/* The newc and crc formats store multiply linked copies of the same file + in the archive only once. The actual data is attached to the last link + in the archive, and the other links all have a filesize of 0. When a + file in the archive has multiple links and a filesize of 0, its data is + probably "attatched" to another file in the archive, so we can't create + it right away. We have to "defer" creating it until we have created + the file that has the data "attatched" to it. We keep a list of the + "defered" links on deferments. */ + +struct deferment *deferments = NULL; + +/* Add a file header to the deferments list. For now they all just + go on one list, although we could optimize this if necessary. */ + +static void +defer_copyin (file_hdr) + struct new_cpio_header *file_hdr; +{ + struct deferment *d; + d = create_deferment (file_hdr); + d->next = deferments; + deferments = d; + return; +} + +/* We just created a file that (probably) has some other links to it + which have been defered. Go through all of the links on the deferments + list and create any which are links to this file. */ + +static void +create_defered_links (file_hdr) + struct new_cpio_header *file_hdr; +{ + struct deferment *d; + struct deferment *d_prev; + int ino; + int maj; + int min; + int link_res; + ino = file_hdr->c_ino; + maj = file_hdr->c_dev_maj; + min = file_hdr->c_dev_min; + d = deferments; + d_prev = NULL; + while (d != NULL) + { + if ( (d->header.c_ino == ino) && (d->header.c_dev_maj == maj) + && (d->header.c_dev_min == min) ) + { + struct deferment *d_free; + link_res = link_to_name (d->header.c_name, file_hdr->c_name); + if (link_res < 0) + { + error (0, errno, "cannot link %s to %s", + d->header.c_name, file_hdr->c_name); + } + if (d_prev != NULL) + d_prev->next = d->next; + else + deferments = d->next; + d_free = d; + d = d->next; + free_deferment (d_free); + } + else + { + d_prev = d; + d = d->next; + } + } +} + +/* If we had a multiply linked file that really was empty then we would + have defered all of its links, since we never found any with data + "attached", and they will still be on the deferment list even when + we are done reading the whole archive. Write out all of these + empty links that are still on the deferments list. */ + +static void +create_final_defers () +{ + struct deferment *d; + int link_res; + int out_file_des; + struct utimbuf times; /* For setting file times. */ + /* Initialize this in case it has members we don't know to set. */ + bzero (×, sizeof (struct utimbuf)); + + for (d = deferments; d != NULL; d = d->next) + { + link_res = link_to_maj_min_ino (d->header.c_name, + d->header.c_dev_maj, d->header.c_dev_maj, + d->header.c_ino); + if (link_res == 0) + { + continue; + } + out_file_des = open (d->header.c_name, + O_CREAT | O_WRONLY | O_BINARY, 0600); + if (out_file_des < 0 && create_dir_flag) + { + create_all_directories (d->header.c_name); + out_file_des = open (d->header.c_name, + O_CREAT | O_WRONLY | O_BINARY, + 0600); + } + if (out_file_des < 0) + { + error (0, errno, "%s", d->header.c_name); + continue; + } + + if (close (out_file_des) < 0) + error (0, errno, "%s", d->header.c_name); + + /* File is now copied; set attributes. */ + if (!no_chown_flag) + if ((chown (d->header.c_name, + set_owner_flag ? set_owner : d->header.c_uid, + set_group_flag ? set_group : d->header.c_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", d->header.c_name); + /* chown may have turned off some permissions we wanted. */ + if (chmod (d->header.c_name, (int) d->header.c_mode) < 0) + error (0, errno, "%s", d->header.c_name); + if (retain_time_flag) + { + times.actime = times.modtime = d->header.c_mtime; + if (utime (d->header.c_name, ×) < 0) + error (0, errno, "%s", d->header.c_name); + } + } +} diff --git a/contrib/cpio/copypass.c b/contrib/cpio/copypass.c new file mode 100644 index 000000000000..9c27ac596348 --- /dev/null +++ b/contrib/cpio/copypass.c @@ -0,0 +1,474 @@ +/* copypass.c - cpio copy pass sub-function. + Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "filetypes.h" +#include "system.h" +#include "cpiohdr.h" +#include "dstring.h" +#include "extern.h" + +#ifndef HAVE_LCHOWN +#define lchown chown +#endif + +/* Copy files listed on the standard input into directory `directory_name'. + If `link_flag', link instead of copying. */ + +void +process_copy_pass () +{ + dynamic_string input_name; /* Name of file from stdin. */ + dynamic_string output_name; /* Name of new file. */ + int dirname_len; /* Length of `directory_name'. */ + int res; /* Result of functions. */ + char *slash; /* For moving past slashes in input name. */ + struct utimbuf times; /* For resetting file times after copy. */ + struct stat in_file_stat; /* Stat record for input file. */ + struct stat out_file_stat; /* Stat record for output file. */ + int in_file_des; /* Input file descriptor. */ + int out_file_des; /* Output file descriptor. */ + int existing_dir; /* True if file is a dir & already exists. */ +#ifdef HPUX_CDF + int cdf_flag; + int cdf_char; +#endif + + /* Initialize the copy pass. */ + dirname_len = strlen (directory_name); + ds_init (&input_name, 128); + ds_init (&output_name, dirname_len + 2); + strcpy (output_name.ds_string, directory_name); + output_name.ds_string[dirname_len] = '/'; + output_is_seekable = TRUE; + /* Initialize this in case it has members we don't know to set. */ + bzero (×, sizeof (struct utimbuf)); + + /* Copy files with names read from stdin. */ + while (ds_fgetstr (stdin, &input_name, name_end) != NULL) + { + int link_res = -1; + + /* Check for blank line and ignore it if found. */ + if (input_name.ds_string[0] == '\0') + { + error (0, 0, "blank line ignored"); + continue; + } + + /* Check for current directory and ignore it if found. */ + if (input_name.ds_string[0] == '.' + && (input_name.ds_string[1] == '\0' + || (input_name.ds_string[1] == '/' + && input_name.ds_string[2] == '\0'))) + continue; + + if ((*xstat) (input_name.ds_string, &in_file_stat) < 0) + { + error (0, errno, "%s", input_name.ds_string); + continue; + } + + /* Make the name of the new file. */ + for (slash = input_name.ds_string; *slash == '/'; ++slash) + ; +#ifdef HPUX_CDF + /* For CDF's we add a 2nd `/' after all "hidden" directories. + This kind of a kludge, but it's what we do when creating + archives, and it's easier to do this than to separately + keep track of which directories in a path are "hidden". */ + slash = add_cdf_double_slashes (slash); +#endif + ds_resize (&output_name, dirname_len + strlen (slash) + 2); + strcpy (output_name.ds_string + dirname_len + 1, slash); + + existing_dir = FALSE; + if (lstat (output_name.ds_string, &out_file_stat) == 0) + { + if (S_ISDIR (out_file_stat.st_mode) + && S_ISDIR (in_file_stat.st_mode)) + { + /* If there is already a directory there that + we are trying to create, don't complain about it. */ + existing_dir = TRUE; + } + else if (!unconditional_flag + && in_file_stat.st_mtime <= out_file_stat.st_mtime) + { + error (0, 0, "%s not created: newer or same age version exists", + output_name.ds_string); + continue; /* Go to the next file. */ + } + else if (S_ISDIR (out_file_stat.st_mode) + ? rmdir (output_name.ds_string) + : unlink (output_name.ds_string)) + { + error (0, errno, "cannot remove current %s", + output_name.ds_string); + continue; /* Go to the next file. */ + } + } + + /* Do the real copy or link. */ + if (S_ISREG (in_file_stat.st_mode)) + { +#ifndef __MSDOS__ + /* Can the current file be linked to a another file? + Set link_name to the original file name. */ + if (link_flag) + /* User said to link it if possible. Try and link to + the original copy. If that fails we'll still try + and link to a copy we've already made. */ + link_res = link_to_name (output_name.ds_string, + input_name.ds_string); + if ( (link_res < 0) && (in_file_stat.st_nlink > 1) ) + link_res = link_to_maj_min_ino (output_name.ds_string, + major (in_file_stat.st_dev), + minor (in_file_stat.st_dev), + in_file_stat.st_ino); +#endif + + /* If the file was not linked, copy contents of file. */ + if (link_res < 0) + { + in_file_des = open (input_name.ds_string, + O_RDONLY | O_BINARY, 0); + if (in_file_des < 0) + { + error (0, errno, "%s", input_name.ds_string); + continue; + } + out_file_des = open (output_name.ds_string, + O_CREAT | O_WRONLY | O_BINARY, 0600); + if (out_file_des < 0 && create_dir_flag) + { + create_all_directories (output_name.ds_string); + out_file_des = open (output_name.ds_string, + O_CREAT | O_WRONLY | O_BINARY, 0600); + } + if (out_file_des < 0) + { + error (0, errno, "%s", output_name.ds_string); + close (in_file_des); + continue; + } + + copy_files_disk_to_disk (in_file_des, out_file_des, in_file_stat.st_size, input_name.ds_string); + disk_empty_output_buffer (out_file_des); + if (close (in_file_des) < 0) + error (0, errno, "%s", input_name.ds_string); + if (close (out_file_des) < 0) + error (0, errno, "%s", output_name.ds_string); + + /* Set the attributes of the new file. */ + if (!no_chown_flag) + if ((chown (output_name.ds_string, + set_owner_flag ? set_owner : in_file_stat.st_uid, + set_group_flag ? set_group : in_file_stat.st_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", output_name.ds_string); + /* chown may have turned off some permissions we wanted. */ + if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0) + error (0, errno, "%s", output_name.ds_string); + if (reset_time_flag) + { + times.actime = in_file_stat.st_atime; + times.modtime = in_file_stat.st_mtime; + if (utime (input_name.ds_string, ×) < 0) + error (0, errno, "%s", input_name.ds_string); + if (utime (output_name.ds_string, ×) < 0) + error (0, errno, "%s", output_name.ds_string); + } + if (retain_time_flag) + { + times.actime = times.modtime = in_file_stat.st_mtime; + if (utime (output_name.ds_string, ×) < 0) + error (0, errno, "%s", output_name.ds_string); + } + } + } + else if (S_ISDIR (in_file_stat.st_mode)) + { +#ifdef HPUX_CDF + cdf_flag = 0; +#endif + if (!existing_dir) + { +#ifdef HPUX_CDF + /* If the directory name ends in a + and is SUID, + then it is a CDF. Strip the trailing + from the name + before creating it. */ + cdf_char = strlen (output_name.ds_string) - 1; + if ( (cdf_char > 0) && + (in_file_stat.st_mode & 04000) && + (output_name.ds_string [cdf_char] == '+') ) + { + output_name.ds_string [cdf_char] = '\0'; + cdf_flag = 1; + } +#endif + res = mkdir (output_name.ds_string, in_file_stat.st_mode); + + } + else + res = 0; + if (res < 0 && create_dir_flag) + { + create_all_directories (output_name.ds_string); + res = mkdir (output_name.ds_string, in_file_stat.st_mode); + } + if (res < 0) + { + /* In some odd cases where the output_name includes `.', + the directory may have actually been created by + create_all_directories(), so the mkdir will fail + because the directory exists. If that's the case, + don't complain about it. */ + if ( (errno != EEXIST) || + (lstat (output_name.ds_string, &out_file_stat) != 0) || + !(S_ISDIR (out_file_stat.st_mode) ) ) + { + error (0, errno, "%s", output_name.ds_string); + continue; + } + } + if (!no_chown_flag) + if ((chown (output_name.ds_string, + set_owner_flag ? set_owner : in_file_stat.st_uid, + set_group_flag ? set_group : in_file_stat.st_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", output_name.ds_string); + /* chown may have turned off some permissions we wanted. */ + if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0) + error (0, errno, "%s", output_name.ds_string); +#ifdef HPUX_CDF + if (cdf_flag) + /* Once we "hide" the directory with the chmod(), + we have to refer to it using name+ isntead of name. */ + output_name.ds_string [cdf_char] = '+'; +#endif + if (retain_time_flag) + { + times.actime = times.modtime = in_file_stat.st_mtime; + if (utime (output_name.ds_string, ×) < 0) + error (0, errno, "%s", output_name.ds_string); + } + } +#ifndef __MSDOS__ + else if (S_ISCHR (in_file_stat.st_mode) || + S_ISBLK (in_file_stat.st_mode) || +#ifdef S_ISFIFO + S_ISFIFO (in_file_stat.st_mode) || +#endif +#ifdef S_ISSOCK + S_ISSOCK (in_file_stat.st_mode) || +#endif + 0) + { + /* Can the current file be linked to a another file? + Set link_name to the original file name. */ + if (link_flag) + /* User said to link it if possible. */ + link_res = link_to_name (output_name.ds_string, + input_name.ds_string); + if ( (link_res < 0) && (in_file_stat.st_nlink > 1) ) + link_res = link_to_maj_min_ino (output_name.ds_string, + major (in_file_stat.st_dev), + minor (in_file_stat.st_dev), + in_file_stat.st_ino); + + if (link_res < 0) + { +#ifdef S_ISFIFO + if (S_ISFIFO (in_file_stat.st_mode)) + res = mkfifo (output_name.ds_string, in_file_stat.st_mode); + else +#endif + res = mknod (output_name.ds_string, in_file_stat.st_mode, + in_file_stat.st_rdev); + if (res < 0 && create_dir_flag) + { + create_all_directories (output_name.ds_string); +#ifdef S_ISFIFO + if (S_ISFIFO (in_file_stat.st_mode)) + res = mkfifo (output_name.ds_string, in_file_stat.st_mode); + else +#endif + res = mknod (output_name.ds_string, in_file_stat.st_mode, + in_file_stat.st_rdev); + } + if (res < 0) + { + error (0, errno, "%s", output_name.ds_string); + continue; + } + if (!no_chown_flag) + if ((chown (output_name.ds_string, + set_owner_flag ? set_owner : in_file_stat.st_uid, + set_group_flag ? set_group : in_file_stat.st_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", output_name.ds_string); + /* chown may have turned off some permissions we wanted. */ + if (chmod (output_name.ds_string, in_file_stat.st_mode) < 0) + error (0, errno, "%s", output_name.ds_string); + if (retain_time_flag) + { + times.actime = times.modtime = in_file_stat.st_mtime; + if (utime (output_name.ds_string, ×) < 0) + error (0, errno, "%s", output_name.ds_string); + } + } + } +#endif + +#ifdef S_ISLNK + else if (S_ISLNK (in_file_stat.st_mode)) + { + char *link_name; + int link_size; + link_name = (char *) xmalloc ((unsigned int) in_file_stat.st_size + 1); + + link_size = readlink (input_name.ds_string, link_name, + in_file_stat.st_size); + if (link_size < 0) + { + error (0, errno, "%s", input_name.ds_string); + free (link_name); + continue; + } + link_name[link_size] = '\0'; + + res = UMASKED_SYMLINK (link_name, output_name.ds_string, + in_file_stat.st_mode); + if (res < 0 && create_dir_flag) + { + create_all_directories (output_name.ds_string); + res = UMASKED_SYMLINK (link_name, output_name.ds_string, + in_file_stat.st_mode); + } + if (res < 0) + { + error (0, errno, "%s", output_name.ds_string); + free (link_name); + continue; + } + + /* Set the attributes of the new link. */ + if (!no_chown_flag) + if ((lchown (output_name.ds_string, + set_owner_flag ? set_owner : in_file_stat.st_uid, + set_group_flag ? set_group : in_file_stat.st_gid) < 0) + && errno != EPERM) + error (0, errno, "%s", output_name.ds_string); + free (link_name); + } +#endif + else + { + error (0, 0, "%s: unknown file type", input_name.ds_string); + } + + if (verbose_flag) + fprintf (stderr, "%s\n", output_name.ds_string); + if (dot_flag) + fputc ('.', stderr); + } + + if (dot_flag) + fputc ('\n', stderr); + if (!quiet_flag) + { + res = (output_bytes + io_block_size - 1) / io_block_size; + if (res == 1) + fprintf (stderr, "1 block\n"); + else + fprintf (stderr, "%d blocks\n", res); + } +} + +/* Try and create a hard link from FILE_NAME to another file + with the given major/minor device number and inode. If no other + file with the same major/minor/inode numbers is known, add this file + to the list of known files and associated major/minor/inode numbers + and return -1. If another file with the same major/minor/inode + numbers is found, try and create another link to it using + link_to_name, and return 0 for success and -1 for failure. */ + +int +link_to_maj_min_ino (file_name, st_dev_maj, st_dev_min, st_ino) + char *file_name; + int st_dev_maj; + int st_dev_min; + int st_ino; +{ + int link_res; + char *link_name; + link_res = -1; +#ifndef __MSDOS__ + /* Is the file a link to a previously copied file? */ + link_name = find_inode_file (st_ino, + st_dev_maj, + st_dev_min); + if (link_name == NULL) + add_inode (st_ino, file_name, + st_dev_maj, + st_dev_min); + else + link_res = link_to_name (file_name, link_name); +#endif + return link_res; +} + +/* Try and create a hard link from LINK_NAME to LINK_TARGET. If + `create_dir_flag' is set, any non-existent (parent) directories + needed by LINK_NAME will be created. If the link is successfully + created and `verbose_flag' is set, print "LINK_TARGET linked to LINK_NAME\n". + If the link can not be created and `link_flag' is set, print + "cannot link LINK_TARGET to LINK_NAME\n". Return 0 if the link + is created, -1 otherwise. */ + +int +link_to_name (link_name, link_target) + char *link_name; + char *link_target; +{ + int res; +#ifdef __MSDOS__ + res = -1; +#else /* not __MSDOS__ */ + res = link (link_target, link_name); + if (res < 0 && create_dir_flag) + { + create_all_directories (link_name); + res = link (link_target, link_name); + } + if (res == 0) + { + if (verbose_flag) + error (0, 0, "%s linked to %s", + link_target, link_name); + } + else if (link_flag) + { + error (0, errno, "cannot link %s to %s", + link_target, link_name); + } +#endif /* not __MSDOS__ */ + return res; +} diff --git a/lib/libalias/alias_old.c b/lib/libalias/alias_old.c new file mode 100644 index 000000000000..3f634d448411 --- /dev/null +++ b/lib/libalias/alias_old.c @@ -0,0 +1,77 @@ +/* + This file can be considered a junk pile of old functions that + are either obsolete or have had their names changed. In the + transition from alias2.1 to alias2.2, all the function names + were rationalized so that they began with "PacketAlias..." + + These functions are included for backwards compatibility. +*/ + +#include <sys/types.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include "alias.h" +#include "alias_local.h" + +void +InitPacketAlias(void) +{ + PacketAliasInit(); +} + +void +SetPacketAliasAddress(struct in_addr addr) +{ + PacketAliasSetAddress(addr); +} + +unsigned int +SetPacketAliasMode(unsigned int flags, unsigned int mask) +{ + return PacketAliasSetMode(flags, mask); +} + +int +PacketAliasPermanentLink(struct in_addr src_addr, u_short src_port, + struct in_addr dst_addr, u_short dst_port, + u_short alias_port, u_char proto) +{ + struct alias_link *link; + struct in_addr null_address; + + null_address.s_addr = 0; + link = PacketAliasRedirectPort(src_addr, src_port, + dst_addr, dst_port, + null_address, alias_port, + proto); + + if (link == NULL) + return -1; + else + return 0; +} + +int +SaveFragmentPtr(char *ptr) +{ + return PacketAliasSaveFragment(ptr); +} + +char * +GetNextFragmentPtr(char *ptr) +{ + return PacketAliasGetFragment(ptr); +} + +void +FragmentAliasIn(char *header, char *fragment) +{ + PacketAliasFragmentIn(header, fragment); +} + +u_short +InternetChecksum(u_short *ptr, int len) +{ + return PacketAliasInternetChecksum(ptr, len); +} diff --git a/lib/libc/gen/sysctlbyname.c b/lib/libc/gen/sysctlbyname.c new file mode 100644 index 000000000000..9c4f34653cc0 --- /dev/null +++ b/lib/libc/gen/sysctlbyname.c @@ -0,0 +1,35 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $Id: sysctlbyname.c,v 1.1 1997/05/30 20:53:13 phk Exp $ + * + */ +#include <sys/types.h> +#include <sys/sysctl.h> + +int +sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp, + size_t newlen) +{ + int name2oid_oid[2]; + int real_oid[CTL_MAXNAME+2]; + int error, oidlen; + + name2oid_oid[0] = 0; /* This is magic & undocumented! */ + name2oid_oid[1] = 3; + + oidlen = sizeof(real_oid); + error = sysctl(name2oid_oid, 2, real_oid, &oidlen, (void *)name, + strlen(name)); + if (error < 0) + return error; + oidlen /= sizeof (int); + error = sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen); + return (error); +} + diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3 new file mode 100644 index 000000000000..bdda0e348cd1 --- /dev/null +++ b/lib/libc/stdtime/strptime.3 @@ -0,0 +1,85 @@ +.\" +.\" Copyright (c) 1997 Joerg Wunsch +.\" +.\" 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 DEVELOPERS 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. +.\" +.\" $Id$ +.\" " +.Dd May 8, 1997 +.Dt STRPTIME 3 +.Os +.Sh NAME +.Nm strptime +.Nd parse date and time string +.Sh SYNOPSIS +.Fd #include <time.h> +.Ft const char * +.Fn strptime "const char *buf" "const char *format" "struct tm *timeptr" +.Sh DESCRIPTION +The +.Fn strptime +function parses the string in the buffer +.Fa buf +according to the string pointed to by +.Fa format , +and fills in the elements of the structure pointed to by +.Fa timeptr . +Thus, it can be considered the reverse operation of +.Xr strftime 3 . +.Pp +The +.Fa format +string consists of zero or more conversion specifications and +ordinary characters. +All ordinary characters are matched exactly with the buffer, where +white space in the format string will match any amount of white space +in the buffer. +All conversion specifications are identical to those described in +.Xr strftime 3 . +.Sh RETURN VALUES +Upon successful completion, +.Fn strptime +returns the pointer to the first character in +.Fa buf +that has not been required to satisfy the specified conversions in +.Fa format . +It returns +.Dv NULL +if one of the conversions failed. +.Sh SEE ALSO +.Xr date 1 , +.Xr scanf 3 , +.Xr strftime 3 +.Sh AUTHORS +The +.Fn strptime +function has been contributed by Powerdog Industries. +.Pp +This man page was written by +.ie t J\(:org Wunsch. +.el Joerg Wunsch. +.Sh HISTORY +The +.Fn strptime +function appeared in +.Fx 3.0 . diff --git a/lib/libc/stdtime/timelocal.c b/lib/libc/stdtime/timelocal.c new file mode 100644 index 000000000000..ef40035c09f4 --- /dev/null +++ b/lib/libc/stdtime/timelocal.c @@ -0,0 +1,197 @@ +/*- + * Copyright (c) 1997 FreeBSD Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $Id$ + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/syslimits.h> +#include <fcntl.h> +#include <locale.h> +#include <stdlib.h> +#include <string.h> +#include "setlocale.h" +#include "timelocal.h" + +struct lc_time_T _time_localebuf; +int _time_using_locale; + +const struct lc_time_T _C_time_locale = { + { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }, { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + }, { + "Sun", "Mon", "Tue", "Wed", + "Thu", "Fri", "Sat" + }, { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" + }, + + /* X_fmt */ + "%H:%M:%S", + + /* + ** x_fmt + ** Since the C language standard calls for + ** "date, using locale's date format," anything goes. + ** Using just numbers (as here) makes Quakers happier; + ** it's also compatible with SVR4. + */ + "%m/%d/%y", + + /* + ** c_fmt (ctime-compatible) + ** Note that + ** "%a %b %d %H:%M:%S %Y" + ** is used by Solaris 2.3. + */ + "%a %b %e %X %Y", + + /* am */ + "AM", + + /* pm */ + "PM", + + /* date_fmt */ + "%a %b %e %X %Z %Y" +}; + + +int +__time_load_locale(const char *name) +{ + static char * locale_buf; + static char locale_buf_C[] = "C"; + + int fd; + char * lbuf; + char * p; + const char ** ap; + const char * plim; + char filename[PATH_MAX]; + struct stat st; + size_t namesize; + size_t bufsize; + int save_using_locale; + + save_using_locale = _time_using_locale; + _time_using_locale = 0; + + if (name == NULL) + goto no_locale; + + if (!strcmp(name, "C") || !strcmp(name, "POSIX")) + return 0; + + /* + ** If the locale name is the same as our cache, use the cache. + */ + lbuf = locale_buf; + if (lbuf != NULL && strcmp(name, lbuf) == 0) { + p = lbuf; + for (ap = (const char **) &_time_localebuf; + ap < (const char **) (&_time_localebuf + 1); + ++ap) + *ap = p += strlen(p) + 1; + _time_using_locale = 1; + return 0; + } + /* + ** Slurp the locale file into the cache. + */ + namesize = strlen(name) + 1; + + if (!_PathLocale) + goto no_locale; + /* Range checking not needed, 'name' size is limited */ + strcpy(filename, _PathLocale); + strcat(filename, "/"); + strcat(filename, name); + strcat(filename, "/LC_TIME"); + fd = open(filename, O_RDONLY); + if (fd < 0) + goto no_locale; + if (fstat(fd, &st) != 0) + goto bad_locale; + if (st.st_size <= 0) + goto bad_locale; + bufsize = namesize + st.st_size; + locale_buf = NULL; + lbuf = (lbuf == NULL || lbuf == locale_buf_C) ? + malloc(bufsize) : realloc(lbuf, bufsize); + if (lbuf == NULL) + goto bad_locale; + (void) strcpy(lbuf, name); + p = lbuf + namesize; + plim = p + st.st_size; + if (read(fd, p, (size_t) st.st_size) != st.st_size) + goto bad_lbuf; + if (close(fd) != 0) + goto bad_lbuf; + /* + ** Parse the locale file into localebuf. + */ + if (plim[-1] != '\n') + goto bad_lbuf; + for (ap = (const char **) &_time_localebuf; + ap < (const char **) (&_time_localebuf + 1); + ++ap) { + if (p == plim) + goto reset_locale; + *ap = p; + while (*p != '\n') + ++p; + *p++ = '\0'; + } + /* + ** Record the successful parse in the cache. + */ + locale_buf = lbuf; + + _time_using_locale = 1; + return 0; + +reset_locale: + /* + * XXX - This may not be the correct thing to do in this case. + * setlocale() assumes that we left the old locale alone. + */ + locale_buf = locale_buf_C; + _time_localebuf = _C_time_locale; + save_using_locale = 0; +bad_lbuf: + free(lbuf); +bad_locale: + (void) close(fd); +no_locale: + _time_using_locale = save_using_locale; + return -1; +} diff --git a/lib/libc/stdtime/timelocal.h b/lib/libc/stdtime/timelocal.h new file mode 100644 index 000000000000..8593aee3ec3e --- /dev/null +++ b/lib/libc/stdtime/timelocal.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1997 FreeBSD Inc. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $Id$ + */ + +/* + * Private header file for the strftime and strptime localization + * stuff. + */ +struct lc_time_T { + const char * mon[12]; + const char * month[12]; + const char * wday[7]; + const char * weekday[7]; + const char * X_fmt; + const char * x_fmt; + const char * c_fmt; + const char * am; + const char * pm; + const char * date_fmt; +}; + +extern struct lc_time_T _time_localebuf; +extern int _time_using_locale; +extern const struct lc_time_T _C_time_locale; + +#define Locale (_time_using_locale ? &_time_localebuf : &_C_time_locale) + diff --git a/release/README.TXT b/release/README.TXT new file mode 100644 index 000000000000..53fd6c839da5 --- /dev/null +++ b/release/README.TXT @@ -0,0 +1,33 @@ +For a normal CDROM or network installation, all you need to copy onto an +actual floppy from this directory is the boot.flp image (for 1.44MB floppies). + +NOTE: These images are NOT DOS files! You cannot simply copy them to +a DOS floppy as regular files, you need to *image* copy them to the +floppy with fdimage.exe under DOS or `dd' under UNIX. + +For example: + +To create the boot floppy image from DOS, you'd do something like +this: + +C> fdimage boot.flp a: + +Assuming that you'd copied fdimage.exe and boot.flp into a directory +somewhere. If you were doing this from the base of a CD distribution, +then the *exact* command would be: + +E> tools\fdimage floppies\boot.flp a: + + +If you're creating the boot floppy from a UNIX machine, you may find +that: + + dd if=floppies/boot.flp of=/dev/rfd0 + +or + + dd if=floppies/boot.flp of=/dev/floppy + +work well, depending on your hardware and operating system environment +(different versions of UNIX have totally different names for the +floppy drive - neat, huh? :-). diff --git a/release/floppies/bin/Makefile b/release/floppies/bin/Makefile new file mode 100644 index 000000000000..15f5ebff4c19 --- /dev/null +++ b/release/floppies/bin/Makefile @@ -0,0 +1,7 @@ +# $Id: Makefile,v 1.1 1997/07/16 12:24:18 julian Exp $ +# +SUBDIR= write_mfs_in_kernel dumpnlist + +.include <bsd.subdir.mk> + + diff --git a/release/floppies/bin/doFS.sh b/release/floppies/bin/doFS.sh new file mode 100644 index 000000000000..f0c2f2b189a3 --- /dev/null +++ b/release/floppies/bin/doFS.sh @@ -0,0 +1,71 @@ +: +#set -ex + +VNDEVICE=vn0 +export BLOCKSIZE=512 + +BOOTBLKDIR=$1 ; shift +MNT=$1 ; shift +FSSIZE=$1 ; shift +FSPROTO=$1 ; shift +FSINODE=$1 ; shift +FSLABEL=$1 ; shift + +deadlock=20 + +while true +do + rm -f fs-image + + if [ ! -b /dev/${VNDEVICE} -o ! -c /dev/r${VNDEVICE} ] ; then + ( cd /dev && sh MAKEDEV ${VNDEVICE} ) + fi + + umount /dev/${VNDEVICE} 2>/dev/null || true + + umount ${MNT} 2>/dev/null || true + + vnconfig -u /dev/r${VNDEVICE} 2>/dev/null || true + + dd of=fs-image if=/dev/zero count=${FSSIZE} bs=1k 2>/dev/null + # this suppresses the `invalid primary partition table: no magic' + awk 'BEGIN {printf "%c%c", 85, 170}' |\ + dd of=fs-image obs=1 seek=510 conv=notrunc 2>/dev/null + + vnconfig -s labels -c /dev/r${VNDEVICE} fs-image + + disklabel -Brw \ + -b ${BOOTBLKDIR}/boot1 \ + -s ${BOOTBLKDIR}/boot2 \ + /dev/r${VNDEVICE} minimum + + TPC=1 + CPD=1 + SPT=$(( 2 * $FSSIZE / 2)) + newfs -u ${SPT} -t ${TPC} -s $(( ${FSSIZE} * 2 )) -i ${FSINODE} -m 0 -o space /dev/r${VNDEVICE}c + + mount /dev/${VNDEVICE}c ${MNT} + + ( set -e && cd ${FSPROTO} && find . -print | cpio -dump ${MNT} ) + + df -ki /mnt + + set `df -ki /mnt | tail -1` + + umount ${MNT} + + fsck -p /dev/r${VNDEVICE}c < /dev/null + + vnconfig -u /dev/r${VNDEVICE} 2>/dev/null || true + + if [ $FSLABEL != "minimum" ] ; then + echo ${FSSIZE} > fs-image.size + break + fi + + echo ">>> Filesystem is ${FSSIZE} K, $4 left" + echo ">>> ${FSINODE} bytes/inode, $7 left" + echo ">>> `expr ${FSSIZE} \* 1024 / ${FSINODE}`" + echo ${FSSIZE} > fs-image.size + break; +done diff --git a/release/floppies/bin/dumpnlist/Makefile b/release/floppies/bin/dumpnlist/Makefile new file mode 100644 index 000000000000..1149cadbbeb6 --- /dev/null +++ b/release/floppies/bin/dumpnlist/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile,v 1.1 1997/07/16 12:24:19 julian Exp $ +# +PROG=dumpnlist +NOMAN=yes + +.include <bsd.prog.mk> + + diff --git a/release/floppies/bin/dumpnlist/dumpnlist.c b/release/floppies/bin/dumpnlist/dumpnlist.c new file mode 100644 index 000000000000..31f25c15879b --- /dev/null +++ b/release/floppies/bin/dumpnlist/dumpnlist.c @@ -0,0 +1,44 @@ +#include <sys/types.h> +#include <sys/fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <nlist.h> +#include <stdio.h> + +struct nlist nl[] = { + {"_isa_devtab_bio"}, + {"_isa_devtab_tty"}, + {"_isa_devtab_net"}, + {"_isa_devtab_null"}, + {"_isa_biotab_wdc"}, + {"_isa_biotab_fdc"}, + {"_eisadriver_set"}, + {"_eisa_dev_list"}, + {"_pcidevice_set"}, + {"_device_list"}, + {"_scbusses"}, + {"_scsi_cinit"}, + {"_scsi_dinit"}, + {"_scsi_tinit"}, + {""}, +}; + +int +main(int ac, char **av) +{ + int i; + + i = nlist(av[1], nl); + if (i == -1) { + fprintf(stderr, "nlist returns error for %s\n", av[1]); + perror("nlist"); + return 1; + } + printf("%d\n", sizeof(nl) / sizeof(struct nlist)); + for (i = 0; nl[i].n_name; i++) { + printf("%s\n", nl[i].n_name); + printf("%d %d %d %ld\n", + nl[i].n_type, nl[i].n_other, nl[i].n_desc, nl[i].n_value); + } + return 0; +} diff --git a/release/floppies/bin/write_mfs_in_kernel/Makefile b/release/floppies/bin/write_mfs_in_kernel/Makefile new file mode 100644 index 000000000000..cd65a8e75249 --- /dev/null +++ b/release/floppies/bin/write_mfs_in_kernel/Makefile @@ -0,0 +1,8 @@ +# $Id: Makefile,v 1.1 1997/07/16 12:24:20 julian Exp $ +# +PROG=write_mfs_in_kernel +NOMAN=yes + +.include <bsd.prog.mk> + + diff --git a/release/floppies/bin/write_mfs_in_kernel/write_mfs_in_kernel.c b/release/floppies/bin/write_mfs_in_kernel/write_mfs_in_kernel.c new file mode 100644 index 000000000000..b624ed6387d4 --- /dev/null +++ b/release/floppies/bin/write_mfs_in_kernel/write_mfs_in_kernel.c @@ -0,0 +1,70 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $Id: write_mfs_in_kernel.c,v 1.1 1997/07/16 12:24:21 julian Exp $ + * + * This program patches a filesystem into a kernel made with MFS_ROOT + * option. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <ufs/ffs/fs.h> + +main(int argc, char **argv) +{ + unsigned char *buf_kernel, *buf_fs, *p,*q; + int fd_kernel, fd_fs; + struct stat st_kernel, st_fs; + u_long l; + + if (argc < 3) { + fprintf(stderr,"Usage:\n\t%s kernel fs\n"); + exit(2); + } + fd_kernel = open(argv[1],O_RDWR); + if (fd_kernel < 0) { perror(argv[1]); exit(2); } + fstat(fd_kernel,&st_kernel); + fd_fs = open(argv[2],O_RDONLY); + if (fd_fs < 0) { perror(argv[2]); exit(2); } + fstat(fd_fs,&st_fs); + buf_kernel = malloc(st_kernel.st_size); + if (!buf_kernel) { perror("malloc"); exit(2); } + buf_fs = malloc(st_fs.st_size); + if (!buf_fs) { perror("malloc"); exit(2); } + if (st_kernel.st_size != read(fd_kernel,buf_kernel,st_kernel.st_size)) + { perror(argv[1]); exit(2); } + if (st_fs.st_size != read(fd_fs,buf_fs,st_fs.st_size)) + { perror(argv[2]); exit(2); } + for(l=0,p=buf_kernel; l < st_kernel.st_size - st_fs.st_size ; l++,p++ ) + if(*p == 'M' && !strcmp(p,"MFS Filesystem goes here")) + goto found; + fprintf(stderr,"MFS filesystem signature not found in %s\n",argv[1]); + exit(1); + found: + for(l=0,q= p + SBOFF; l < st_fs.st_size - SBOFF ; l++,q++ ) + if (*q) + goto fail; + memcpy(p+SBOFF,buf_fs+SBOFF,st_fs.st_size-SBOFF); + lseek(fd_kernel,0L,SEEK_SET); + if (st_kernel.st_size != write(fd_kernel,buf_kernel,st_kernel.st_size)) + { perror(argv[1]); exit(2); } + exit(0); + fail: + l += SBOFF; + fprintf(stderr,"Obstruction in kernel after %ld bytes (%ld Kbyte)\n", + l, l/1024); + fprintf(stderr,"Filesystem is %ld bytes (%ld Kbyte)\n", + (u_long)st_fs.st_size, (u_long)st_fs.st_size/1024); + exit(1); +} diff --git a/release/floppies/mk/crunch_fs.mk b/release/floppies/mk/crunch_fs.mk new file mode 100644 index 000000000000..c6d51d19bf8e --- /dev/null +++ b/release/floppies/mk/crunch_fs.mk @@ -0,0 +1,108 @@ +### +# $Id: crunch_fs.mk,v 1.1 1997/07/16 12:24:29 julian Exp $ +# +# This is included to make a floppy that includes a crunch file +# +# Variables that control this mk include file. +# TOP specifies where the top of the FreeBSD source tree is.. (*) +# FS_DIRS directories to make on the fs (*) +# STANDLINKS added symlinks to /stand on the fs +# VERBATIM a directory that contains tree to be copied to the fs +# FSSIZE defaults to 1440 +# FSLABEL defaults to fd1440 +# FSINODE defaults to 4000 +# FS_DEVICES devices to make on the fs (using MAKEDEV) (default = all) +# ZIP decides if the installed cruch will also be gzip'd(def=true) +# (*) = Mandatory +### + +# If we weren't told, default to nothing +.if ! defined( TOP ) +# define TOP! +xxx +.endif + +# mountpoint for filesystems. +MNT= /mnt + +# other floppy parameters. +FSSIZE?= 1440 +FSLABEL?= fd1440 +FSINODE?= 2000 +FS_DEVICES?= all +ZIP?=true + +# Things which will get you into trouble if you change them +TREE= tree +LABELDIR= ${OBJTOP}/sys/i386/boot/biosboot + +clean: + rm -rf tree fs-image fs-image.size step[0-9] + +.include <bsd.prog.mk> + + +# +# --==## Create a filesystem image ##==-- +# + +fs_image: ${TREE} step2 step3 step4 fs-image + +${TREE}: ${.CURDIR}/Makefile + rm -rf ${TREE} + mkdir -p ${TREE} + cd ${TREE} && mkdir ${FS_DIRS} + cd ${TREE} ; for i in ${STANDLINKS} ; \ + do \ + ln -s /stand $${i} ; \ + done + +step2: ${.CURDIR}/${CRUNCHDIRS} ${.CURDIR}/Makefile +.if defined(CRUNCHDIRS) + @cd ${.CURDIR} && $(MAKE) installCRUNCH DIR=${TREE}/stand ZIP=${ZIP} +.endif + touch step2 + +step3: step2 +.if defined (FS_DEVICES) + ( cd tree/dev && \ + cp ${TOP}/etc/etc.i386/MAKEDEV . && sh MAKEDEV ${FS_DEVICES} ) +.endif + touch step3 + +step4: step3 +.if defined(VERBATIM) + A=`pwd`;cd ${.CURDIR}/${VERBATIM}; \ + find . \! \( -name CVS -and -prune \) -print |cpio -pdmuv $$A/tree +.endif + true || cp ${TOP}/etc/spwd.db tree/etc + touch step4 + +fs-image: step4 + sh -e ${SCRIPTDIR}/doFS.sh ${LABELDIR} ${MNT} ${FSSIZE} tree \ + ${FSINODE} ${FSLABEL} + cp fs-image.size ${.CURDIR} + + +.if defined(CRUNCHDIRS) +installCRUNCH: +.if !defined(DIR) + @echo "DIR undefined in installCRUNCH" && exit 1 +.endif +.if !defined(ZIP) + @echo "ZIP undefined in installCRUNCH" && exit 1 +.endif +.for CRUNCHDIR in ${CRUNCHDIRS} + if ${ZIP} ; then \ + gzip -9 < ${CRUNCHDIR}/crunch > ${DIR}/.crunch ; \ + else \ + ln -f ${CRUNCHDIR}/crunch ${DIR}/.crunch ; \ + fi + chmod 555 ${DIR}/.crunch + for i in `crunchgen -l ${.CURDIR}/${CRUNCHDIR}/crunch.conf` ; do \ + ln -f ${DIR}/.crunch ${DIR}/$$i ; \ + done + rm -f ${DIR}/.crunch +.endfor +.endif + diff --git a/release/floppies/mk/makecrunch.mk b/release/floppies/mk/makecrunch.mk new file mode 100644 index 000000000000..8f2d3e70afe1 --- /dev/null +++ b/release/floppies/mk/makecrunch.mk @@ -0,0 +1,25 @@ + + +SYSINSTALL= ${OBJTOP}/release/sysinstall/sysinstall + +NOCRYPT?= yes + +all: crunch + +crunch: + -crunchgen ${.CURDIR}/crunch.conf + ${MAKE} -f crunch.mk all NOCRYP=${NOCRYPT} \ + "CFLAGS=${CFLAGS} -DCRUNCHED_BINARY" + +clean: + rm -f *.o *.stub *.lo *_stub.c *.mk \ + crunch.cache \ + crunch.mk \ + crunch.c \ + crunch \ + .tmp_* + +install: + @echo " No idea what to do to install yet" + +.include <bsd.prog.mk> diff --git a/release/sysinstall/sysinstall.8 b/release/sysinstall/sysinstall.8 new file mode 100644 index 000000000000..52011c3dc427 --- /dev/null +++ b/release/sysinstall/sysinstall.8 @@ -0,0 +1,784 @@ +.\" Copyright (c) 1997 +.\" Jordan Hubbard <jkh@freebsd.org>. 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. +.\" +.\" THIS SOFTWARE IS PROVIDED BY Jordan Hubbard 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 Jordan Hubbard 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. +.\" +.\" $Id$ +.\" +.Dd August 9, 1997 +.Dt SYSINSTALL 8 +.Os +.Sh NAME +.Nm sysinstall +.Nd system installation and configuration tool +.Sh SYNOPSIS +.Nm +.Op Ar var=value +.Op Ar sub-function +.Op Ar ... +.Sh DESCRIPTION +.Nm +is a utility for installing and configuring FreeBSD systems; +it is the first utility invoked by the FreeBSD installation boot +floppy and is also copied into +.Pa /stand +on newly installed FreeBSD systems so that it may be run +later to further configure the system. +.Pp +The +.Nm +program is generally invoked without arguments for the default +behavior which brings up the main installation/configuration menu. + +On those occasions where it is deemed necessary to invoke a subsystem +of sysinstall directly, however, it is also possible to do so by +naming the appropriate function entry points on the command line. +Since this action is essentially identical to running an installation +script, with each argument corresponding to a line of script, the +reader is encouraged to read the section on scripting for more +information on this feature. +.Pp +.Sh NOTES +.Nm +is essentially nothing more than a monolithic C program with +the ability to write MBRs and disk labels (through the services +of the +.Xr libdisk 3 +library) and install distributions or packages onto new and +existing FreeBSD systems. It also contains some extra intelligence +for running as a replacement for +.Xr init 8 +when it's invoked by the FreeBSD installation boot procedure. It +assumes very little in the way of additional utility support and +performs most file operations by calling the relevant syscalls +(such as +.Xr mount 2 ) +directly. +.Pp +.Nm +currently uses the +.Xr libdialog 3 +library to do user interaction with simple ANSI line graphics, color +support for which is enabled by either running on a syscons VTY or some +other color-capable terminal emulator (newer versions of xterm will support +color when using the ``xterm-color'' termcap entry). +.Pp +This product is currently at the end of its life cycle and will +be replaced in FreeBSD 3.0 by the +.Xr setup 1 +utility. +.Sh RUNNING SCRIPTS +.Nm +may be either driven interactively through its various internal menus +or run in batch mode, driven by an external script. Such scripts can +be loaded and executed in one of 3 ways: + +.Bl -tag -width Ds -compact +.It Sy "LOAD_CONFIG_FILE" +If +.Nm +is compiled with LOAD_CONFIG_FILE set in the environment +(or in the Makefile) to some value, then that value will +be used as the filename to automatically look for and load +when +.Nm +starts up, no interaction on the part of the user being required. +This option is aimed primarily at large sites who wish to create a +single prototype install for multiple machines with largely identical +configurations and/or installation options. + +.It Sy "MAIN MENU" +If +.Nm +is run interactively, that is to say in the default manner, it will +bring up a main menu which contains a "load config file" option. +Selecting this option will allow the name of a script file to be +specified and loaded from a DOS or UFS formatted floppy. + +.It Sy "COMMAND LINE" +In the same fashion that script directives may be specified one +operation per line in a file, so may each command line argument +be a directive +when +.Nm +is run in multi-user mode. Execution ends either by explicit request +(e.g. calling the +.Ar shutdown +directive), upon reaching the end of the argument list or on error. +.Pp +For example: +.nf + +/stand/sysinstall ftp=ftp:/ziggy/pub/ mediaSetFTP configPackages + +.fi +Would initialize +.Nm +for FTP installation media (using the server `ziggy') and then +bring up the package installation editor. When the package editor +exits, so will +.Nm +.El +.Pp +.Sh SCRIPT SYNTAX +A script is given one or more directives, each directive taking +the form of: + +.Ar var=value +.Ar function +or +.Ar #somecomment + +Where +.Ar var=value +is the assignment of some internal +.Nm +variable, e.g. "ftpPass=FuNkYChiKn", and +.Ar function +is the name of an internal +.Nm +function, e.g. "mediaSetFTP", and +.Ar #comment +is a single-line comment for documentation purposes (ignored by +sysinstall). Functions take their arguments by examining known +variable names, requiring that you be sure to assign those values +first before calling the function. Where a function in the table +below takes such arguments, they will be documented there. +.Pp +\fBFunction Glossary:\fR +.Pp +.Bl -tag -width indent +.It configAnonFTP +Invoke the Anonymous FTP configuration menu. +.Pp +\fBVariables:\fR None +.It configRouter +Select which routing daemon you wish to use, potentially +loading any required 3rd-party routing daemons as necessary. +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It router +can be set to the name of the desired routing daemon, +e.g. ``routed'' or ``gated'', otherwise it is prompted for. +.El +.It configNFSServer +Configure host as an NFS server. +.Pp +\fBVariables:\fR None +.It configNTP +Configure host as a user of the Network Time Protocol. +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It ntpdate_flags +The flags to +.Xr ntpdate 8 , +that is to say the name of the server to sync from. +.El +.It configPCNFSD +Configure host to support PC NFS. +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It pcnfsd_pkg +The name of the PCNFSD package to load if necessary (defaults to hard coded +version). +.El +.It configPackages +Bring up the interactive package management menu. +.Pp +\fBVariables:\fR None +.It configRegister +Register the user with the FreeBSD counter. +.Pp +\fBVariables:\fR None +.It configUsers +Add users and/or groups to the system. +.Pp +\fBVariables:\fR None +.It configXEnvironment +Configure the X display subsystem. +.Pp +\fBVariables:\fR None +.It diskPartitionEditor +Invokes the disk partition (MBR) editor. +.Pp +\fBVariables:\fR +.Bl -tag -width findx +.It geometry +The disk geometry, as a cyls/heads/sectors formatted string. Default: no +change to geometry. +.It partition +Set to disk partitioning type or size, its value being +.Ar free +in order to use only remaining free space for FreeBSD, +.Ar all +to use the entire disk for FreeBSD but maintain a proper partition +table, +.Ar existing +to use an existing FreeBSD partition (first found), +.Ar exclusive +to use the disk in ``dangerously dedicated'' mode or, finally, +.Ar somenumber +to allocate +.Ar somenumber +blocks of available free space to a new FreeBSD partition. +Default: Interactive mode. +.It bootManager +is set to one of +.Ar boot +to signify the installation of a boot manager, +.Ar standard +to signify installation of a "standard" non-boot MGR DOS +MBR or +.Ar none +to indicate that no change to the boot manager is desired. +Default: none. +.El +.Pp +Note: Nothing is actually written to disk by this function, a explicit call to +.Ar diskPartitionWrite +being required for that to happen. +.It diskPartitionWrite +Causes any pending MBR changes (typically from the +.Ar diskPartitionEditor ) +to be written out. +.Pp +\fBVariables:\fR None +.It diskLabelEditor +Invokes the disk label editor. This is a bit trickier from a script +since you need to essentially label everything inside each FreeBSD +(type 0xA5) partition created by the +.Ar diskPartitionEditor +function, and that requires knowing a few rules about how things are +laid out. When creating a script to automatically allocate disk space +and partition it up, it is suggested that you first perform the +installation interactively at least once and take careful notes as to +what the slice names will be, then and only then hardwiring them into +the script. +.Pp +For example, let's say you have a SCSI disk on which you've created a new +FreeBSD partition in slice 2 (your DOS partition residing in slice 1). +The slice name would be +.Ar sd0s2 +for the whole FreeBSD partition ( +.Ar sd0s1 +being your DOS primary +partition). Now let's further assume that you have 500MB in this +partition and you want to sub-partition that space into root, swap, +var and usr file systems for FreeBSD. Your invocation of the +.Ar diskLabelEditor +function might involve setting the following variables: +.Bl -tag -width findx +.It Li "sd0s2-1=ufs 40960 /" +A 20MB root file system (all sizes are in 512 byte blocks). +.It Li "sd0s2-2=swap 131072 /" +A 64MB swap partition. +.It Li "sd0s2-3=ufs 204800 /var" +A 100MB /var file system. +.It Li "sd0s2-4=ufs 0 /usr" +With the balance of free space (around 316MB) going to the /usr +file system. +.El + +One can also use the +.Ar diskLabelEditor +for mounting or erasing existing partitions as well as creating new +ones. Using the previous example again, let's say that we also wanted +to mount our DOS partition and make sure that an +.Pa /etc/fstab +entry is created for it in the new installation. Before calling the +.Ar diskLabelEditor +function, we simply add an additional line: +.nf + sd0s1=/dos_c N + +.fi +before the call. This tells the label editor that you want to mount +the first slice on +.Pa /dos_c +and not to attempt to newfs it (not that +.Nm +would attempt this for a DOS partition in any case, but it could just +as easily be an existing UFS partition being named here and the 2nd +field is non-optional). +.Pp +Note: No file system data is actually written to disk until an +explicit call to +.Ar diskLabelCommit +is made. +.It diskLabelCommit +Writes out all pending disklabel information and creates and/or mounts any +file systems which have requests pending from the +.Ar diskLabelEditor +function. +.Pp +\fBVariables:\fR None +.It distReset +Resets all selected distributions to the empty set (no distributions selected). +.Pp +\fBVariables:\fR None +.It distSetCustom +Allows the selection of a custom distribution set (e.g. not just on of the +existing "canned" sets) with no user interaction. +\fBVariables:\fR +.Bl -tag -width indent +.It dists +List of distributions to load. Possible distribution values are: +.Bl -tag -width indent +.It Li bin +The base binary distribution. +.It Li doc +Miscellaneous documentation +.It Li games +Games +.It Li manpages +Manual pages (unformatted) +.It Li catpages +Pre-formatted manual pages +.It Li proflibs +Profiled libraries for developers. +.It Li dict +Dictionary information (for tools like spell). +.It Li info +GNU info files and other extra docs. +.It Li des +DES encryption binaries and libraries. +.It Li compat1x +Compatibility with FreeBSD 1.x +.It Li compat20 +Compatibility with FreeBSD 2.0 +.It Li compat21 +Compatibility with FreeBSD 2.1 +.It Li ports +The ports collection. +.It Li krb +Kerberos binaries. +.It Li ssecure +/usr/src/secure +.It Li sebones +/usr/src/eBones +.It Li sbase +/usr/src/[top level files] +.It Li scontrib +/usr/src/contrib +.It Li sgnu +/usr/src/gnu +.It Li setc +/usr/src/etc +.It Li sgames +/usr/src/games +.It Li sinclude +/usr/src/include +.It Li slib +/usr/src/lib +.It Li slibexec +/usr/src/libexec +.It Li slkm +/usr/src/lkm +.It Li srelease +/usr/src/release +.It Li sbin +/usr/src/bin +.It Li ssbin +/usr/src/sbin +.It Li sshare +/usr/src/share +.It Li ssys +/usr/src/sys +.It Li subin +/usr/src/usr.bin +.It Li susbin +/usr/src/usr.sbin +.It Li ssmailcf +/usr/src/usr.sbin/sendmail/cf +.It Li XF86-xc +XFree86 official sources. +.It Li XF86-co +XFree86 contributed sources. +.It Li X33bin +XFree86 3.3 binaries. +.It Li X33cfg +XFree86 3.3 configuration files. +.It Li X33doc +XFree86 3.3 documentation. +.It Li X33html +XFree86 3.3 HTML documentation. +.It Li X33lib +XFree86 3.3 libraries. +.It Li X33lk98 +XFree86 3.3 server link-kit for PC98 machines. +.It Li X33lkit +XFree86 3.3 server link-kit for standard machines. +.It Li X33man +XFree86 3.3 manual pages. +.It Li X33prog +XFree86 3.3 programmer's distribution. +.It Li X33ps +XFree86 3.3 postscript documentation. +.It Li X33set +XFree86 3.3 graphical setup tool. +.It Li X338514 +XFree86 3.3 8514 server. +.It Li X339480 +XFree86 3.3 PC98 8-bit (256 color) PEGC-480 server. +.It Li X339EGC +XFree86 3.3 PC98 4-bit (16 color) EGC server. +.It Li X339GA9 +XFree86 3.3 PC98 GA-968V4/PCI (S3 968) server. +.It Li X339GAN +XFree86 3.3 PC98 GANB-WAP (cirrus) server. +.It Li X339LPW +XFree86 3.3 PC98 PowerWindowLB (S3) server. +.It Li X339NKV +XFree86 3.3 PC98 NKV-NEC (cirrus) server. +.It Li X339NS3 +XFree86 3.3 PC98 NEC (S3) server. +.It Li X339SPW +XFree86 3.3 PC98 SKB-PowerWindow (S3) server. +.It Li X339TGU +XFree86 3.3 PC98 Cyber9320 and TGUI9680 server. +.It Li X339WEP +XFree86 3.3 PC98 WAB-EP (cirrus) server. +.It Li X339WS +XFree86 3.3 PC98 WABS (cirrus) server. +.It Li X339WSN +XFree86 3.3 PC98 WSN-A2F (cirrus) server. +.It Li X33AGX +XFree86 3.3 8 bit AGX server. +.It Li X33I128 +XFree86 3.3 #9 Imagine I128 server. +.It Li X33Ma8 +XFree86 3.3 ATI Mach8 server. +.It Li X33Ma32 +XFree86 3.3 ATI Mach32 server. +.It Li X33Ma64 +XFree86 3.3 ATI Mach64 server. +.It Li X33Mono +XFree86 3.3 monochrome server. +.It Li X33P9K +XFree86 3.3 P9000 server. +.It Li X33S3 +XFree86 3.3 S3 server. +.It Li X33S3V +XFree86 3.3 S3 Virge server. +.It Li X33SVGA +XFree86 3.3 SVGA server. +.It Li X33VG16 +XFree86 3.3 VGA16 server. +.It Li X33W32 +XFree86 3.3 ET4000/W32, /W32i and /W32p server. +.It Li X33nest +XFree86 3.3 nested X server. +.It Li X33vfb +XFree86 3.3 virtual frame-buffer X server. +.It Li X33fnts +XFree86 3.3 base font set. +.It Li X33f100 +XFree86 3.3 100DPI font set. +.It Li X33fcyr +XFree86 3.3 Cyrillic font set. +.It Li X33fscl +XFree86 3.3 scalable font set. +.It Li X33fnon +XFree86 3.3 non-english font set. +.It Li X33fsrv +XFree86 3.3 font server. +.El +.It distSetDeveloper +Selects the standard Developer's distribution set. +.Pp +\fBVariables:\fR None +.It distSetXDeveloper +Selects the standard X Developer's distribution set. +.Pp +\fBVariables:\fR None +.It distSetKernDeveloper +Selects the standard kernel Developer's distribution set. +.Pp +\fBVariables:\fR None +.It distSetUser +Selects the standard user distribution set. +.Pp +\fBVariables:\fR None +.It distSetXUser +Selects the standard X user's distribution set. +.Pp +\fBVariables:\fR None +.It distSetMinimum +Selects the very minimum distribution set. +.Pp +\fBVariables:\fR None +.It distSetEverything +Selects the full whack - all available distributions. +.Pp +\fBVariables:\fR None +.It distSetDES +Interactively select DES subcomponents. +.Pp +\fBVariables:\fR None +.It distSetSrc +Interactively select source subcomponents. +.Pp +\fBVariables:\fR None +.It distSetXF86 +Interactively select XFree86 3.3 subcomponents. +.Pp +\fBVariables:\fR None +.It distExtractAll +Install all currently selected distributions (requires that +media device also be selected). +.Pp +\fBVariables:\fR None +.It docBrowser +Install (if necessary) an HTML documentation browser and go to the +HTML documentation submenu. +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It browserPackage +The name of the browser package to try and install as necessary. +Defaults to latest lynx package. +.It browserBinary +The name of the browser binary itself (if overriding the +.Ar browserPackage +variable). Defaults to lynx. +.El +.It installCommit +.Pp +Commit any and all pending changes to disk. This function +is essentially shorthand for a number of more granular "commit" +functions. +\fBVariables:\fR None +.It installExpress +Start an "express" installation, asking few questions of +the user. +.Pp +\fBVariables:\fR None +.It installNovice +Start a "novice" installation, the most user-friendly +installation type available. +.Pp +\fBVariables:\fR None +.It installUpgrade +Start an upgrade installation. +.Pp +\fBVariables:\fR None +.It installFixitHoloShell +Start up the "emergency holographic shell" over on VTY4 +if running as init. +.Pp +\fBVariables:\fR None +.It installFixitCDROM +Go into "fixit" mode, assuming a live file system CDROM +currently in the drive. +.Pp +\fBVariables:\fR None +.It installFixitFloppy +Go into "fixit" mode, assuming an available fixit floppy +disk (user will be prompted for it). +.Pp +\fBVariables:\fR None +.It installFilesystems +Do just the file system initialization part of an install. +.Pp +\fBVariables:\fR None +.It installVarDefaults +Initialize all variables to their defaults, overriding any +previous settings. +.Pp +\fBVariables:\fR None +.It mediaSetCDROM +Select a FreeBSD CDROM as the installation media. +.Pp +\fBVariables:\fR None +.It mediaSetFloppy +Select a pre-made floppy installation set as the installation media. +.Pp +\fBVariables:\fR None +.It mediaSetDOS +Select an existing DOS primary partition as the installation media. +The first primary partition found is used (e.g. C:). +.Pp +\fBVariables:\fR None +.It mediaSetTape +Select a tape device as the installation media. +.Pp +\fBVariables:\fR None +.It mediaSetFTP +Select an FTP site as the installation media. +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It hostname +The name of the host being installed (optional). +.It domainname +The domain name of the host being installed (optional). +.It defaultrouter +The default router for this host (non-optional). +.It netDev +Which host interface to use ( +.Ar ed0 +or +.Ar ep0 , +for example. Non-optional). +.It ipaddr +The IP address for the selected host interface (non-optional). +.It netmask +The netmask for the selected host interface (non-optional). +.It ftp +The fully qualified URL of the FTP site containing the FreeBSD +distribution you're interested in, e.g. +.Ar ftp://ftp.freebsd.org/pub/FreeBSD/ . +.El +.It mediaSetFTPActive +Alias for +.Ar mediaSetFTP +using "active" FTP transfer mode. +.Pp +\fBVariables:\fR Same as for +.Ar mediaSetFTP . +.It mediaSetFTPPassive +Alias for +.Ar mediaSetFTP +using "passive" FTP transfer mode. +.Pp +\fBVariables:\fR Same as for +.Ar mediaSetFTP . +.It mediaSetUFS +Select an existing UFS partition (mounted with the label editor) as +the installation media. +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It ufs +full /path to directory containing the FreeBSD distribution you're +interested in. +.El +.It mediaSetNFS +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It hostname +The name of the host being installed (optional). +.It domainname +The domain name of the host being installed (optional). +.It defaultrouter +The default router for this host (non-optional). +.It netDev +Which host interface to use ( +.Ar ed0 +or +.Ar ep0 , +for example. Non-optional). +.It ipaddr +The IP address for the selected host interface (non-optional). +.It netmask +The netmask for the selected host interface (non-optional). +.It nfs +full hostname:/path specification for directory containing +the FreeBSD distribution you're interested in. +.El +.It mediaSetFTPUserPass +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It ftpUser +The username to log in as on the ftp server site. +Default: ftp +.It ftpPass +The password to use for this username on the ftp +server site. +Default: user@host +.El +.It mediaSetCPIOVerbosity +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It cpioVerbose +Can be used to set the verbosity of cpio extractions to low, medium or +high. +.El +.It mediaGetType +Interactively get the user to specify some type of media. +.Pp +\fBVariables:\fR None +.It optionsEditor +Invoke the interactive options editor. +.Pp +\fBVariables:\fR None +.It register +Bring up the FreeBSD registration form. +.Pp +\fBVariables:\fR None +.It packageAdd +Try to fetch and add a package to the system (requires +that a media type be set), +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It package +The name of the package to add, e.g. bash-1.14.7 or ncftp-2.4.2. +.El +.It addGroup +Invoke the interactive group editor. +.Pp +\fBVariables:\fR None +.It addUser +Invoke the interactive user editor. +.Pp +\fBVariables:\fR None +.It shutdown +Stop the script and terminate sysinstall. +.Pp +\fBVariables:\fR None +.It system +Execute an arbitrary command with +.Xr system 3 +.Pp +\fBVariables:\fR +.Bl -tag -width indent +.It command +The name of the command to execute. When running +from a boot floppy, very minimal expectations should +be made as to what's available until/unless a relatively +full system installation has just been done. +.El +.El +.Sh FILES +This utility may edit the contents of +.Pa /etc/rc.conf , +.Pa /etc/hosts , +and +.Pa /etc/resolv.conf +as necessary to reflect changes in the network configuration. +.Sh BUGS +This utility is a prototype which lasted approximately 2 years past +its expiration date and is greatly in need of death. +.Sh AUTHOR +Jordan K. Hubbard <jkh@FreeBSD.org> +.Sh HISTORY +This version of +.Nm +first appeared in +.Fx 2.0 . diff --git a/share/man/man4/man4.i386/sb.4 b/share/man/man4/man4.i386/sb.4 new file mode 100644 index 000000000000..e6cda477118f --- /dev/null +++ b/share/man/man4/man4.i386/sb.4 @@ -0,0 +1,73 @@ +.\" Man page for the SoundBlaster driver +.\" +.\" Copyright (c) 1997, Alex Zepeda. +.\" +.\" This documentation is public domain, and is provided without warranty. +.\" Alex Zepeda, the "author" of this page is not resposible for any +.\" consequences of any sort of manipulation of this document. +.\" +.\" SoundBlaster and any phrases including it's name are copyright +.\" Creative Labs, not me. +.\" +.\" alex!@bigfoot.com +.\" +.Dd August 9, 1997 +.Dt SB 4 i386 +.Os FreeBSD +.Sh NAME +.Nm sb +.Nd Creative Labs Sound Blaster and compatable device driver +.Sh SYNOPSIS +For all sound cards supported with the sb driver this is needed: +.Cd controller snd0 +.Pp +For the SoundBlaster, SB Pro, SoundBlaster16, or the Pro Audio Spectrum + (emulating SB): +.Cd "device sb0 at isa? port 0x220 irq 7 drq 1 vector sbintr" +.Pp +For specific SB16 support: +.Cd "device sbxvi0 at isa? drq 5" +.Pp +For SoundBlaster 16 16 bit MIDI support: +.Cd "device sbmidi0 at isa? port 0x300" +.Pp +To add Jazz16 suport: +.Cd "options JAZZ16" +.Pp +To add support for the Logitech SoundMan Games: +.Cd "options SM_GAMES" +.Pp +To add SG NX Pro mixer support: +.Cd "options __SGNXPRO__" +.Pp +The OPL-2/3 is used in the SoundBlaster, SoundBlaster Pro, SB 16, and the +Pro Audio Spectrum. For Yamaha OPL-2/OPL-3 FM support: +.Cd "device opl0 at isa? port 0x388" +.Sh DESCRIPTION +This driver covers the SoundBlaster family of cards including the +SoundBlaster 1.0 to the SoundBlaster 16/SoundBlaster 32. The awe driver +provides AWE32/64 functionality. This driver is provied in FreeBSD +versions 2.0-current through 3.0-current. You can also configure more +then one card on a single DMA using the conflicts keyword in your +configuration file. This is useful for boards with more then one type of +emulation. +.Sh BUGS +Since the SB16 uses the same IRQ and addresses for +the different drivers, some of the snd drivers will not be probed because +the kernel thinks there is a conflict. This can be worked-around by +using the "conflicts" keyword on the sb16's device line. +.Pp +Current version doesn't support mode changes without closing and reopening +the device. Support for this feature may be implemented in a future +version of this driver. +.Sh SEE ALSO +cdcontrol(1), cdplay(1), mixer(8) +.Sh AUTHORS +The original SoundBlaster DSP and SoundBlaster 16 MIDI, and Yamaha OPL-3 +drivers were written by Hannu Savolainen. The SoundBlaster 16 DSP code +was written by J. Schuber (jsb@sth.ruhr-uni-bochum.de). Improvments to +the OPL-3 drivers were made by Rob Hooft (hooft@chem.ruu.nl) +.Sh HISTORY +Sound Galaxy NX Pro support added by Hunyue Yau (Jan 6 1994). MV +ProSonic/Jazz 16 16bit support added by JRA Gibson (April 1995). Audio +Excel DSP 16 support added by Riccardo Facchetti (March 24 1995). diff --git a/share/man/man4/man4.i386/wl.4 b/share/man/man4/man4.i386/wl.4 new file mode 100644 index 000000000000..114ef0f588f7 --- /dev/null +++ b/share/man/man4/man4.i386/wl.4 @@ -0,0 +1,147 @@ +.\" +.\" Copyright (c) 1997, Jim Binkley +.\" 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 Jim Binkley +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +.\" +.\" $Id$ +.Dd July 7, 1997 +.Dt WL 4 i386 +.Os FreeBSD +.Sh NAME +.Nm wl +.Nd T1 speed ISA/radio lan card +.Sh SYNOPSIS +.Cd "device wl0 at isa? port 0x300 net irq 5 vector wlintr" +.Sh DESCRIPTION +The +.Nm wl +driver controls a radio lan card system made originally by +NCR, then ATT, now Lucent. The system is spread-spectrum radio +at around 915 mhz (or 2.4 ghz). With the supplied omni-directional antennae, +about 400 feet (indoors, more outdoors) can be covered in circumference. +This card can talk to the companion (wlp0) pccard. Speeds vary +from 1 megabit to theoretically 2 megabits (roughly T1 in speed). +.Pp +The card has 3 fundmental hardware +units, a so-called PSA or programmable storage area, a radio modem, +and a ethernet lan controller. The latter component is the +ancient (and not very honorable) Intel 82586 ethernet chip. +Fundamentally it appears to the operating system as an ethernet system, +and speaks IEEE MAC addresses. The radio modem simply translates +ethernet packets to/from radio packets, that are either at 2.4 Ghz +or 915 mhz depending on the radio modem. It supports a collision +avoidance scheme. The lan controller +supports promiscuous mode, broadcast, and multicasting +(although there is a glitch +in the latter). "It thinks it is ethernet". +.Pp +How it is used +depends on the kind of antennae deployed with it. Point to point +applications are possible as are ethernet-like lan use. The vendor +ships an omni-directional antennae that works in the +vicinity of 400 feet (indoors). +Point to point antennae can be purchased that will go miles. +.Sh SETUP +The card can either be initialized with the vendor supplied DOS setup software. +Typically minimally an IRQ, port, and Network ID must be supplied. +Michael Smith's +.Nm wlconfig(8) +utility can now be used to do this work from +the UNIX side. The card is "not" plug and play. +The network id controls whether one set of cards can hear another. +If different, cards will read physical packets, but they will be discarded +by the radio modem. +.Sh CONTROL +In addition to the config utility, there are several sysctl +switches that can be used to modify runtime parameters. +The +.Nm sysctl(8) +variables are as follows: +.Bl -diag +.It "machdep.wl_xmit_delay <useconds>" +This variable will cause the driver to insert a delay on transmit. +250 is the default. The delay should probably be a bit longer +on faster cpus and less on slower cpus. It exists because the 82586 +was not designed to work with pentium-speed cpu systems and if overdriven +will have copious xmit side errors. +.It machdep.wl_ignore_nwid <0 | 1> +This switch defaults to 0; i.e., the nwid is not ignored. It can +be set to 1 to cause the nwid to not be used. This may be useful +when the device is in promiscuous mode as one can watch for all +packets and ignore nwid differences. +.It machdep.wl_xmit_watch <milliseconds> +This switch is not currently useful. +.It machdep.wl_gather_snr <milliseconds> +This switch is not currently useful. +.Pp +There is also a signal strength cache in the driver. It may be interrogated +with +.Nm wlconfig(8) . +Incoming packets +are checked for certain hardware radio-modem values including signal +strength, silence, and quality, which range fro 0..63, 0..63, and 0..15 +respectively. Thus one can read out signal strenth values to see +how close/far peer nodes are. The signal strength cache is indexed by +sender MAC address. +There are two sysctls that change how it filters packets. Both are on +by default. +.It machdep.wl_wlcache_mcastonly <0 | 1> +By default this switch is on. It forces the cache to filter out +unicast packets. Only broadcast or multicast packets are accepted. +.It machdep.wl_wlcache_iponly <0 | 1> +By default this switch is on. It forces the driver to discard non-IP +packets and also stores the IP src address. ARP packets are ignored, +as are any other network protocol barring IPv4 packets. +.El +.Sh CAVEATS +The 82586 has numerous defects. It may experience transmit-side +errors when modern faster cpus send packets at it faster than it can handle. +The driver (and probably the chip) does not support an all multicast mode. +As a result, it can be used with applications like mrouted(8), but +it must go into promiscuous mode for that to work. The driver +is slow to change modes from "normal" to promiscuous mode, presumably +due to delays in the configuration code. +.Sh SEE ALSO +.Xr wlconfig 8 , +.Xr sysctl 8 , +.Xr http://www.wavelan.com +.Sh HISTORY +The +.Nm wl +driver was written by Anders Klemets (thousands of years ago?) and +appears to be based on an even older Intel 82586 driver. The 82586 +controller was one of the first (if not the first?) integrated lan +controller on the block. That does not mean it was the best either. +Anders ported and or created a driver for the ISA wavelan and PCCARD +wavelan system too (wlp). Robert T. Morris, Jr. ported the Mach +drivers to BSDI. Jim Binkley ported them to FreeBSD 2.1. Michael +Smith ported the wl driver only to 2.2.2. Jim and Michael have been +maintaining them. The current state of the driver is NOT ANYONE'S +FAULT. Thanks to Bernie Doehner and Robert Buaas for contributions. +.Sh AUTHOR +Too numerous to mention. See above. diff --git a/share/skel/dot.shrc b/share/skel/dot.shrc new file mode 100644 index 000000000000..57103fe49a2e --- /dev/null +++ b/share/skel/dot.shrc @@ -0,0 +1,43 @@ +# $Id: dot.profile,v 1.12 1997/07/15 09:37:02 charnier Exp $ +# +# .shrc - bourne shell startup file +# +# This file will be used if the shell is invoked for interactive use and +# the environment variable ENV is set to this file. +# +# see also sh(1), environ(7). +# + + +# file permissions: rwxr-xr-x +# +# umask 022 + +# Uncomment next line to enable the builtin emacs(1) command line editor +# in sh(1), e.g. C-a -> beginning-of-line. +# set -o emacs + + +# some useful aliases +alias h='fc -l' +alias j=jobs +alias m=$PAGER +alias ll='ls -laFo' +alias l='ls -l' +alias g='egrep -i' + +# # be paranoid +# alias cp='cp -ip' +# alias mv='mv -i' +# alias rm='rm -i' + + +# # set prompt: ``username@hostname$ '' +# PS1="`whoami`@`hostname | sed 's/\..*//'`" +# case `id -u` in +# 0) PS1="${PS1}# ";; +# *) PS1="${PS1}$ ";; +# esac + +# search path for cd(1) +# CDPATH=.:$HOME diff --git a/sys/i386/boot/biosboot/boot.help b/sys/i386/boot/biosboot/boot.help new file mode 100644 index 000000000000..7cbce1354839 --- /dev/null +++ b/sys/i386/boot/biosboot/boot.help @@ -0,0 +1,18 @@ +Usage: bios_drive:interface(unit,partition)kernel_name options + bios_drive 0, 1, ... + interface fd, wd or sd + unit 0, 1, ... + partition a, c, ... + kernel_name name of kernel, or ? for list of files in root directory + options -a (ask name) -C (cdrom) -c (userconfig) -D (dual consoles) + -d (debug early) -g (gdb) -h (serial console) -P (probe kbd) + -r (default root) -s (single user) -v (verbose) +Examples: + 1:sd(0,a)mykernel boot `mykernel' on the first SCSI drive when one IDE + drive is present + 1:wd(2,a) boot from the second (secondary master) IDE drive + 1:sd(0,a)? list the files in the root directory on the specified + drive/unit/partition, and set the default bios_drive, + interface, unit and partition + -cv boot with the defaults, then run UserConfig to modify + hardware parameters (c), and print verbose messages (v) diff --git a/sys/i386/include/if_wl_wavelan.h b/sys/i386/include/if_wl_wavelan.h new file mode 100644 index 000000000000..c75a1aecf770 --- /dev/null +++ b/sys/i386/include/if_wl_wavelan.h @@ -0,0 +1,167 @@ +/* $Id$ */ +/* + * 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 all copyright + * notices, this list of conditions and the following disclaimer. + * 2. The names of the authors may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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 _CHIPS_WAVELAN_H +#define _CHIPS_WAVELAN_H + +/* This file contains definitions that are common for all versions of + * the NCR WaveLAN + */ + +#define WAVELAN_ADDR_SIZE 6 /* Size of a MAC address */ +#define WAVELAN_MTU 1500 /* Maximum size of Wavelan packet */ + +/* Modem Management Controler write commands */ +#define MMC_ENCR_KEY 0x00 /* to 0x07 */ +#define MMC_ENCR_ENABLE 0x08 +#define MMC_DES_IO_INVERT 0x0a +#define MMC_LOOPT_SEL 0x10 +#define MMC_JABBER_ENABLE 0x11 +#define MMC_FREEZE 0x12 +#define MMC_ANTEN_SEL 0x13 +#define MMC_IFS 0x14 +#define MMC_MOD_DELAY 0x15 +#define MMC_JAM_TIME 0x16 +#define MMC_THR_PRE_SET 0x18 +#define MMC_DECAY_PRM 0x19 +#define MMC_DECAY_UPDAT_PRM 0x1a +#define MMC_QUALITY_THR 0x1b +#define MMC_NETW_ID_L 0x1c +#define MMC_NETW_ID_H 0x1d +#define MMC_MODE_SEL 0x1e +#define MMC_EECTRL 0x20 /* 2.4 Gz */ +#define MMC_EEADDR 0x21 /* 2.4 Gz */ +#define MMC_EEDATAL 0x22 /* 2.4 Gz */ +#define MMC_EEDATAH 0x23 /* 2.4 Gz */ +#define MMC_ANALCTRL 0x24 /* 2.4 Gz */ + +/* fields in MMC registers that relate to EEPROM in WaveMODEM daughtercard */ +#define MMC_EECTRL_EEPRE 0x10 /* 2.4 Gz EEPROM Protect Reg Enable */ +#define MMC_EECTRL_DWLD 0x08 /* 2.4 Gz EEPROM Download Synths */ +#define MMC_EECTRL_EEOP 0x07 /* 2.4 Gz EEPROM Opcode mask */ +#define MMC_EECTRL_EEOP_READ 0x06 /* 2.4 Gz EEPROM Read Opcode */ +#define MMC_EEADDR_CHAN 0xf0 /* 2.4 Gz EEPROM Channel # mask */ +#define MMC_EEADDR_WDCNT 0x0f /* 2.4 Gz EEPROM DNLD WordCount-1 */ +#define MMC_ANALCTRL_ANTPOL 0x02 /* 2.4 Gz Antenna Polarity mask */ +#define MMC_ANALCTRL_EXTANT 0x01 /* 2.4 Gz External Antenna mask */ + +/* MMC read register names */ +#define MMC_DCE_STATUS 0x10 +#define MMC_CORRECT_NWID_L 0x14 +#define MMC_CORRECT_NWID_H 0x15 +#define MMC_WRONG_NWID_L 0x16 +#define MMC_WRONG_NWID_H 0x17 +#define MMC_THR_PRE_SET 0x18 +#define MMC_SIGNAL_LVL 0x19 +#define MMC_SILENCE_LVL 0x1a +#define MMC_SIGN_QUAL 0x1b +#define MMC_DES_AVAIL 0x09 +#define MMC_EECTRLstat 0x20 /* 2.4 Gz EEPROM r/w/dwld status */ +#define MMC_EEDATALrv 0x22 /* 2.4 Gz EEPROM read value */ +#define MMC_EEDATAHrv 0x23 /* 2.4 Gz EEPROM read value */ + +/* fields in MMC registers that relate to EEPROM in WaveMODEM daughtercard */ +#define MMC_EECTRLstat_ID24 0xf0 /* 2.4 Gz =A0 rev-A, =B0 rev-B */ +#define MMC_EECTRLstat_DWLD 0x08 /* 2.4 Gz Synth/Tx-Pwr DWLD busy */ +#define MMC_EECTRLstat_EEBUSY 0x04 /* 2.4 Gz EEPROM busy */ + +#endif _CHIPS_WAVELAN_H + +/* additional socket ioctl params for wl card + * see sys/sockio.h for numbers. The 2nd params here + * must be greater than any values in sockio.h + */ + +#define SIOCGWLCNWID _IOWR('i', 60, struct ifreq) /* get wlan current nwid */ +#define SIOCSWLCNWID _IOWR('i', 61, struct ifreq) /* set wlan current nwid */ +#define SIOCGWLPSA _IOWR('i', 62, struct ifreq) /* get wlan PSA (all) */ +#define SIOCSWLPSA _IOWR('i', 63, struct ifreq) /* set wlan PSA (all) */ +#define SIOCDWLCACHE _IOW('i', 64, struct ifreq) /* clear SNR cache */ +#define SIOCSWLTHR _IOW('i', 65, struct ifreq) /* set new quality threshold */ +#define SIOCGWLEEPROM _IOWR('i', 66, struct ifreq) /* get modem EEPROM */ +#define SIOCGWLCACHE _IOWR('i', 67, struct ifreq) /* get SNR cache */ +#define SIOCGWLCITEM _IOWR('i', 68, struct ifreq) /* get cache element count */ + +/* PSA address definitions */ +#define WLPSA_ID 0x0 /* ID byte (0 for ISA, 0x14 for MCA) */ +#define WLPSA_IO1 0x1 /* I/O address 1 */ +#define WLPSA_IO2 0x2 /* I/O address 2 */ +#define WLPSA_IO3 0x3 /* I/O address 3 */ +#define WLPSA_BR1 0x4 /* Bootrom address 1 */ +#define WLPSA_BR2 0x5 /* Bootrom address 2 */ +#define WLPSA_BR3 0x6 /* Bootrom address 3 */ +#define WLPSA_HWCONF 0x7 /* HW config bits */ +#define WLPSA_IRQNO 0x8 /* IRQ value */ +#define WLPSA_UNIMAC 0x10 /* Universal MAC address */ +#define WLPSA_LOCALMAC 0x16 /* Locally configured MAC address */ +#define WLPSA_MACSEL 0x1c /* MAC selector */ +#define WLPSA_COMPATNO 0x1d /* compatability number */ +#define WLPSA_THRESH 0x1e /* RF modem threshold preset */ +#define WLPSA_FEATSEL 0x1f /* feature select */ +#define WLPSA_SUBBAND 0x20 /* subband selector */ +#define WLPSA_QUALTHRESH 0x21 /* RF modem quality threshold preset */ +#define WLPSA_HWVERSION 0x22 /* hardware version indicator */ +#define WLPSA_NWID 0x23 /* network ID */ +#define WLPSA_NWIDENABLE 0x24 /* network ID enable */ +#define WLPSA_SECURITY 0x25 /* datalink security enable */ +#define WLPSA_DESKEY 0x26 /* datalink security DES key */ +#define WLPSA_DBWIDTH 0x2f /* databus width select */ +#define WLPSA_CALLCODE 0x30 /* call code (japan only) */ +#define WLPSA_CONFIGURED 0x3c /* configuration status */ +#define WLPSA_CRCLOW 0x3d /* CRC-16 (lowbyte) */ +#define WLPSA_CRCHIGH 0x3e /* (highbyte) */ +#define WLPSA_CRCOK 0x3f /* CRC OK flag */ + +#define WLPSA_COMPATNO_WL24B 0x04 /* 2.4 Gz WaveMODEM ISA rev-B */ + +/* + * signal strength cache + * + * driver (wlp only at the moment) keeps cache of last + * IP (only) packets to arrive including signal strength info. + * daemons may read this with kvm. See if_wlp.c for globals + * that may be accessed through kvm. + * + * Each entry in the w_sigcache has a unique macsrc and age. + * Each entry is identified by its macsrc field. + * Age of the packet is identified by its age field. + */ + +#define MAXCACHEITEMS 10 +#ifndef INT_MAX +#define INT_MAX 2147483647 +#endif +#define MAX_AGE (INT_MAX - MAXCACHEITEMS) + +/* signal is 7 bits, 0..63, although it doesn't seem to get to 63. + * silence is 7 bits, 0..63 + * quality is 4 bits, 0..15 + */ +struct w_sigcache { + char macsrc[6]; /* unique MAC address for entry */ + int ipsrc; /* ip address associated with packet */ + int signal; /* signal strength of the packet */ + int silence; /* silence of the packet */ + int quality; /* quality of the packet */ + int snr; /* packet has unique age between 1 to MAX_AGE - 1 */ +}; + diff --git a/sys/pci/dc21040reg.h b/sys/pci/dc21040reg.h new file mode 100644 index 000000000000..ec274709ccaf --- /dev/null +++ b/sys/pci/dc21040reg.h @@ -0,0 +1,598 @@ +/*- + * Copyright (c) 1994, 1995, 1996 Matt Thomas <matt@3am-software.com> + * 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. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * $Id: dc21040reg.h,v 1.24 1997/05/16 19:47:09 thomas Exp $ + */ + +#if !defined(_DC21040_H) +#define _DC21040_H + +#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN +#define TULIP_BITFIELD2(a, b) b, a +#define TULIP_BITFIELD3(a, b, c) c, b, a +#define TULIP_BITFIELD4(a, b, c, d) d, c, b, a +#else +#define TULIP_BITFIELD2(a, b) a, b +#define TULIP_BITFIELD3(a, b, c) a, b, c +#define TULIP_BITFIELD4(a, b, c, d) a, b, c, d +#endif + +typedef struct { + u_int32_t d_status; + u_int32_t TULIP_BITFIELD3(d_length1 : 11, + d_length2 : 11, + d_flag : 10); + u_int32_t d_addr1; + u_int32_t d_addr2; +} tulip_desc_t; + +#define TULIP_DSTS_OWNER 0x80000000 /* Owner (1 = 21040) */ +#define TULIP_DSTS_ERRSUM 0x00008000 /* Error Summary */ +/* + * Transmit Status + */ +#define TULIP_DSTS_TxBABBLE 0x00004000 /* Transmitter Babbled */ +#define TULIP_DSTS_TxCARRLOSS 0x00000800 /* Carrier Loss */ +#define TULIP_DSTS_TxNOCARR 0x00000400 /* No Carrier */ +#define TULIP_DSTS_TxLATECOLL 0x00000200 /* Late Collision */ +#define TULIP_DSTS_TxEXCCOLL 0x00000100 /* Excessive Collisions */ +#define TULIP_DSTS_TxNOHRTBT 0x00000080 /* No Heartbeat */ +#define TULIP_DSTS_TxCOLLMASK 0x00000078 /* Collision Count (mask) */ +#define TULIP_DSTS_V_TxCOLLCNT 0x00000003 /* Collision Count (bit) */ +#define TULIP_DSTS_TxLINKFAIL 0x00000004 /* Link Failure */ +#define TULIP_DSTS_TxUNDERFLOW 0x00000002 /* Underflow Error */ +#define TULIP_DSTS_TxDEFERRED 0x00000001 /* Initially Deferred */ +/* + * Receive Status + */ +#define TULIP_DSTS_RxBADLENGTH 0x00004000 /* Length Error */ +#define TULIP_DSTS_RxDATATYPE 0x00003000 /* Data Type */ +#define TULIP_DSTS_RxRUNT 0x00000800 /* Runt Frame */ +#define TULIP_DSTS_RxMULTICAST 0x00000400 /* Multicast Frame */ +#define TULIP_DSTS_RxFIRSTDESC 0x00000200 /* First Descriptor */ +#define TULIP_DSTS_RxLASTDESC 0x00000100 /* Last Descriptor */ +#define TULIP_DSTS_RxTOOLONG 0x00000080 /* Frame Too Long */ +#define TULIP_DSTS_RxCOLLSEEN 0x00000040 /* Collision Seen */ +#define TULIP_DSTS_RxFRAMETYPE 0x00000020 /* Frame Type */ +#define TULIP_DSTS_RxWATCHDOG 0x00000010 /* Receive Watchdog */ +#define TULIP_DSTS_RxDRBBLBIT 0x00000004 /* Dribble Bit */ +#define TULIP_DSTS_RxBADCRC 0x00000002 /* CRC Error */ +#define TULIP_DSTS_RxOVERFLOW 0x00000001 /* Overflow */ + + +#define TULIP_DFLAG_ENDRING 0x0008 /* End of Transmit Ring */ +#define TULIP_DFLAG_CHAIN 0x0004 /* Chain using d_addr2 */ + +#define TULIP_DFLAG_TxWANTINTR 0x0200 /* Signal Interrupt on Completion */ +#define TULIP_DFLAG_TxLASTSEG 0x0100 /* Last Segment */ +#define TULIP_DFLAG_TxFIRSTSEG 0x0080 /* First Segment */ +#define TULIP_DFLAG_TxINVRSFILT 0x0040 /* Inverse Filtering */ +#define TULIP_DFLAG_TxSETUPPKT 0x0020 /* Setup Packet */ +#define TULIP_DFLAG_TxHASCRC 0x0010 /* Don't Append the CRC */ +#define TULIP_DFLAG_TxNOPADDING 0x0002 /* Don't AutoPad */ +#define TULIP_DFLAG_TxHASHFILT 0x0001 /* Hash/Perfect Filtering */ + +/* + * The 21040 Registers (IO Space Addresses) + */ +#define TULIP_REG_BUSMODE 0x00 /* CSR0 -- Bus Mode */ +#define TULIP_REG_TXPOLL 0x08 /* CSR1 -- Transmit Poll Demand */ +#define TULIP_REG_RXPOLL 0x10 /* CSR2 -- Receive Poll Demand */ +#define TULIP_REG_RXLIST 0x18 /* CSR3 -- Receive List Base Addr */ +#define TULIP_REG_TXLIST 0x20 /* CSR4 -- Transmit List Base Addr */ +#define TULIP_REG_STATUS 0x28 /* CSR5 -- Status */ +#define TULIP_REG_CMD 0x30 /* CSR6 -- Command */ +#define TULIP_REG_INTR 0x38 /* CSR7 -- Interrupt Control */ +#define TULIP_REG_MISSES 0x40 /* CSR8 -- Missed Frame Counter */ +#define TULIP_REG_ADDRROM 0x48 /* CSR9 -- ENET ROM Register */ +#define TULIP_REG_RSRVD 0x50 /* CSR10 -- Reserved */ +#define TULIP_REG_FULL_DUPLEX 0x58 /* CSR11 -- Full Duplex */ +#define TULIP_REG_SIA_STATUS 0x60 /* CSR12 -- SIA Status */ +#define TULIP_REG_SIA_CONN 0x68 /* CSR13 -- SIA Connectivity */ +#define TULIP_REG_SIA_TXRX 0x70 /* CSR14 -- SIA Tx Rx */ +#define TULIP_REG_SIA_GEN 0x78 /* CSR15 -- SIA General */ + +/* + * CSR5 -- Status Register + * CSR7 -- Interrupt Control + */ +#define TULIP_STS_ERRORMASK 0x03800000L /* ( R) Error Bits (Valid when SYSERROR is set) */ +#define TULIP_STS_ERR_PARITY 0x00000000L /* 000 - Parity Error (Perform Reset) */ +#define TULIP_STS_ERR_MASTER 0x00800000L /* 001 - Master Abort */ +#define TULIP_STS_ERR_TARGET 0x01000000L /* 010 - Target Abort */ +#define TULIP_STS_ERR_SHIFT 23 +#define TULIP_STS_TXSTATEMASK 0x00700000L /* ( R) Transmission Process State */ +#define TULIP_STS_TXS_RESET 0x00000000L /* 000 - Rset or transmit jabber expired */ +#define TULIP_STS_TXS_FETCH 0x00100000L /* 001 - Fetching transmit descriptor */ +#define TULIP_STS_TXS_WAITEND 0x00200000L /* 010 - Wait for end of transmission */ +#define TULIP_STS_TXS_READING 0x00300000L /* 011 - Read buffer and enqueue data */ +#define TULIP_STS_TXS_RSRVD 0x00400000L /* 100 - Reserved */ +#define TULIP_STS_TXS_SETUP 0x00500000L /* 101 - Setup Packet */ +#define TULIP_STS_TXS_SUSPEND 0x00600000L /* 110 - Transmit FIFO underflow or an + unavailable transmit descriptor */ +#define TULIP_STS_TXS_CLOSE 0x00700000L /* 111 - Close transmit descriptor */ +#define TULIP_STS_RXSTATEMASK 0x000E0000L /* ( R) Receive Process State*/ +#define TULIP_STS_RXS_STOPPED 0x00000000L /* 000 - Stopped */ +#define TULIP_STS_RXS_FETCH 0x00020000L /* 001 - Running -- Fetch receive descriptor */ +#define TULIP_STS_RXS_ENDCHECK 0x00040000L /* 010 - Running -- Check for end of receive + packet before prefetch of next descriptor */ +#define TULIP_STS_RXS_WAIT 0x00060000L /* 011 - Running -- Wait for receive packet */ +#define TULIP_STS_RXS_SUSPEND 0x00080000L /* 100 - Suspended -- As a result of + unavailable receive buffers */ +#define TULIP_STS_RXS_CLOSE 0x000A0000L /* 101 - Running -- Close receive descriptor */ +#define TULIP_STS_RXS_FLUSH 0x000C0000L /* 110 - Running -- Flush the current frame + from the receive FIFO as a result of + an unavailable receive buffer */ +#define TULIP_STS_RXS_DEQUEUE 0x000E0000L /* 111 - Running -- Dequeue the receive frame + from the receive FIFO into the receive + buffer. */ +#define TULIP_STS_NORMALINTR 0x00010000L /* (RW) Normal Interrupt */ +#define TULIP_STS_ABNRMLINTR 0x00008000L /* (RW) Abnormal Interrupt */ +#define TULIP_STS_SYSERROR 0x00002000L /* (RW) System Error */ +#define TULIP_STS_LINKFAIL 0x00001000L /* (RW) Link Failure (21040) */ +#define TULIP_STS_FULDPLXSHRT 0x00000800L /* (RW) Full Duplex Short Fram Rcvd (21040) */ +#define TULIP_STS_GPTIMEOUT 0x00000800L /* (RW) General Purpose Timeout (21140) */ +#define TULIP_STS_AUI 0x00000400L /* (RW) AUI/TP Switch (21040) */ +#define TULIP_STS_RXTIMEOUT 0x00000200L /* (RW) Receive Watchbog Timeout */ +#define TULIP_STS_RXSTOPPED 0x00000100L /* (RW) Receive Process Stopped */ +#define TULIP_STS_RXNOBUF 0x00000080L /* (RW) Receive Buffer Unavailable */ +#define TULIP_STS_RXINTR 0x00000040L /* (RW) Receive Interrupt */ +#define TULIP_STS_TXUNDERFLOW 0x00000020L /* (RW) Transmit Underflow */ +#define TULIP_STS_LINKPASS 0x00000010L /* (RW) LinkPass (21041) */ +#define TULIP_STS_TXBABBLE 0x00000008L /* (RW) Transmit Jabber Timeout */ +#define TULIP_STS_TXNOBUF 0x00000004L /* (RW) Transmit Buffer Unavailable */ +#define TULIP_STS_TXSTOPPED 0x00000002L /* (RW) Transmit Process Stopped */ +#define TULIP_STS_TXINTR 0x00000001L /* (RW) Transmit Interrupt */ + +/* + * CSR6 -- Command (Operation Mode) Register + */ +#define TULIP_CMD_MUSTBEONE 0x02000000L /* (RW) Must Be One (21140) */ +#define TULIP_CMD_SCRAMBLER 0x01000000L /* (RW) Scrambler Mode (21140) */ +#define TULIP_CMD_PCSFUNCTION 0x00800000L /* (RW) PCS Function (21140) */ +#define TULIP_CMD_TXTHRSHLDCTL 0x00400000L /* (RW) Transmit Threshold Mode (21140) */ +#define TULIP_CMD_STOREFWD 0x00200000L /* (RW) Store and Foward (21140) */ +#define TULIP_CMD_NOHEARTBEAT 0x00080000L /* (RW) No Heartbeat (21140) */ +#define TULIP_CMD_PORTSELECT 0x00040000L /* (RW) Post Select (100Mb) (21140) */ +#define TULIP_CMD_ENHCAPTEFFCT 0x00040000L /* (RW) Enhanced Capture Effecty (21041) */ +#define TULIP_CMD_CAPTREFFCT 0x00020000L /* (RW) Capture Effect (!802.3) */ +#define TULIP_CMD_BACKPRESSURE 0x00010000L /* (RW) Back Pressure (!802.3) (21040) */ +#define TULIP_CMD_THRESHOLDCTL 0x0000C000L /* (RW) Threshold Control */ +#define TULIP_CMD_THRSHLD72 0x00000000L /* 00 - 72 Bytes */ +#define TULIP_CMD_THRSHLD96 0x00004000L /* 01 - 96 Bytes */ +#define TULIP_CMD_THRSHLD128 0x00008000L /* 10 - 128 bytes */ +#define TULIP_CMD_THRSHLD160 0x0000C000L /* 11 - 160 Bytes */ +#define TULIP_CMD_TXRUN 0x00002000L /* (RW) Start/Stop Transmitter */ +#define TULIP_CMD_FORCECOLL 0x00001000L /* (RW) Force Collisions */ +#define TULIP_CMD_OPERMODE 0x00000C00L /* (RW) Operating Mode */ +#define TULIP_CMD_FULLDUPLEX 0x00000200L /* (RW) Full Duplex Mode */ +#define TULIP_CMD_FLAKYOSCDIS 0x00000100L /* (RW) Flakey Oscillator Disable */ +#define TULIP_CMD_ALLMULTI 0x00000080L /* (RW) Pass All Multicasts */ +#define TULIP_CMD_PROMISCUOUS 0x00000040L /* (RW) Promiscuous Mode */ +#define TULIP_CMD_BACKOFFCTR 0x00000020L /* (RW) Start/Stop Backoff Counter (!802.3) */ +#define TULIP_CMD_INVFILTER 0x00000010L /* (R ) Inverse Filtering */ +#define TULIP_CMD_PASSBADPKT 0x00000008L /* (RW) Pass Bad Frames */ +#define TULIP_CMD_HASHONLYFLTR 0x00000004L /* (R ) Hash Only Filtering */ +#define TULIP_CMD_RXRUN 0x00000002L /* (RW) Start/Stop Receive Filtering */ +#define TULIP_CMD_HASHPRFCTFLTR 0x00000001L /* (R ) Hash/Perfect Receive Filtering */ + +#define TULIP_SIASTS_OTHERRXACTIVITY 0x00000200L +#define TULIP_SIASTS_RXACTIVITY 0x00000100L +#define TULIP_SIASTS_LINKFAIL 0x00000004L +#define TULIP_SIACONN_RESET 0x00000000L + +/* + * 21040 SIA definitions + */ +#define TULIP_21040_PROBE_10BASET_TIMEOUT 2500 +#define TULIP_21040_PROBE_AUIBNC_TIMEOUT 300 +#define TULIP_21040_PROBE_EXTSIA_TIMEOUT 300 + +#define TULIP_21040_SIACONN_10BASET 0x00008F01L +#define TULIP_21040_SIATXRX_10BASET 0x0000FFFFL +#define TULIP_21040_SIAGEN_10BASET 0x00000000L + +#define TULIP_21040_SIACONN_10BASET_FD 0x00008F01L +#define TULIP_21040_SIATXRX_10BASET_FD 0x0000FFFDL +#define TULIP_21040_SIAGEN_10BASET_FD 0x00000000L + +#define TULIP_21040_SIACONN_AUIBNC 0x00008F09L +#define TULIP_21040_SIATXRX_AUIBNC 0x00000705L +#define TULIP_21040_SIAGEN_AUIBNC 0x00000006L + +#define TULIP_21040_SIACONN_EXTSIA 0x00003041L +#define TULIP_21040_SIATXRX_EXTSIA 0x00000000L +#define TULIP_21040_SIAGEN_EXTSIA 0x00000006L + +/* + * 21041 SIA definitions + */ + +#define TULIP_21041_PROBE_10BASET_TIMEOUT 2500 +#define TULIP_21041_PROBE_AUIBNC_TIMEOUT 300 + +#define TULIP_21041_SIACONN_10BASET 0x0000EF01L +#define TULIP_21041_SIATXRX_10BASET 0x0000FF3FL +#define TULIP_21041_SIAGEN_10BASET 0x00000000L + +#define TULIP_21041P2_SIACONN_10BASET 0x0000EF01L +#define TULIP_21041P2_SIATXRX_10BASET 0x0000FFFFL +#define TULIP_21041P2_SIAGEN_10BASET 0x00000000L + +#define TULIP_21041_SIACONN_10BASET_FD 0x0000EF01L +#define TULIP_21041_SIATXRX_10BASET_FD 0x0000FF3DL +#define TULIP_21041_SIAGEN_10BASET_FD 0x00000000L + +#define TULIP_21041P2_SIACONN_10BASET_FD 0x0000EF01L +#define TULIP_21041P2_SIATXRX_10BASET_FD 0x0000FFFFL +#define TULIP_21041P2_SIAGEN_10BASET_FD 0x00000000L + +#define TULIP_21041_SIACONN_AUI 0x0000EF09L +#define TULIP_21041_SIATXRX_AUI 0x0000F73DL +#define TULIP_21041_SIAGEN_AUI 0x0000000EL + +#define TULIP_21041P2_SIACONN_AUI 0x0000EF09L +#define TULIP_21041P2_SIATXRX_AUI 0x0000F7FDL +#define TULIP_21041P2_SIAGEN_AUI 0x0000000EL + +#define TULIP_21041_SIACONN_BNC 0x0000EF09L +#define TULIP_21041_SIATXRX_BNC 0x0000F73DL +#define TULIP_21041_SIAGEN_BNC 0x00000006L + +#define TULIP_21041P2_SIACONN_BNC 0x0000EF09L +#define TULIP_21041P2_SIATXRX_BNC 0x0000F7FDL +#define TULIP_21041P2_SIAGEN_BNC 0x00000006L + +/* + * 21142 SIA definitions + */ + +#define TULIP_21142_PROBE_10BASET_TIMEOUT 2500 +#define TULIP_21142_PROBE_AUIBNC_TIMEOUT 300 + +#define TULIP_21142_SIACONN_10BASET 0x00000001L +#define TULIP_21142_SIATXRX_10BASET 0x0000F3FFL +#define TULIP_21142_SIAGEN_10BASET 0x00000000L + +#define TULIP_21142_SIACONN_10BASET_FD 0x00000001L +#define TULIP_21142_SIATXRX_10BASET_FD 0x0000F3FDL +#define TULIP_21142_SIAGEN_10BASET_FD 0x00000000L + +#define TULIP_21142_SIACONN_AUI 0x00000009L +#define TULIP_21142_SIATXRX_AUI 0x0000F3FDL +#define TULIP_21142_SIAGEN_AUI 0x0000000EL + +#define TULIP_21142_SIACONN_BNC 0x00000009L +#define TULIP_21142_SIATXRX_BNC 0x0000F3FDL +#define TULIP_21142_SIAGEN_BNC 0x00000006L + + + + +#define TULIP_WATCHDOG_TXDISABLE 0x00000001L +#define TULIP_WATCHDOG_RXDISABLE 0x00000010L + +#define TULIP_BUSMODE_SWRESET 0x00000001L +#define TULIP_BUSMODE_DESCSKIPLEN_MASK 0x0000007CL +#define TULIP_BUSMODE_BIGENDIAN 0x00000080L +#define TULIP_BUSMODE_BURSTLEN_MASK 0x00003F00L +#define TULIP_BUSMODE_BURSTLEN_DEFAULT 0x00000000L +#define TULIP_BUSMODE_BURSTLEN_1LW 0x00000100L +#define TULIP_BUSMODE_BURSTLEN_2LW 0x00000200L +#define TULIP_BUSMODE_BURSTLEN_4LW 0x00000400L +#define TULIP_BUSMODE_BURSTLEN_8LW 0x00000800L +#define TULIP_BUSMODE_BURSTLEN_16LW 0x00001000L +#define TULIP_BUSMODE_BURSTLEN_32LW 0x00002000L +#define TULIP_BUSMODE_CACHE_NOALIGN 0x00000000L +#define TULIP_BUSMODE_CACHE_ALIGN8 0x00004000L +#define TULIP_BUSMODE_CACHE_ALIGN16 0x00008000L +#define TULIP_BUSMODE_CACHE_ALIGN32 0x0000C000L +#define TULIP_BUSMODE_TXPOLL_NEVER 0x00000000L +#define TULIP_BUSMODE_TXPOLL_200000ns 0x00020000L +#define TULIP_BUSMODE_TXPOLL_800000ns 0x00040000L +#define TULIP_BUSMODE_TXPOLL_1600000ns 0x00060000L +#define TULIP_BUSMODE_TXPOLL_12800ns 0x00080000L /* 21041 only */ +#define TULIP_BUSMODE_TXPOLL_25600ns 0x000A0000L /* 21041 only */ +#define TULIP_BUSMODE_TXPOLL_51200ns 0x000C0000L /* 21041 only */ +#define TULIP_BUSMODE_TXPOLL_102400ns 0x000E0000L /* 21041 only */ +#define TULIP_BUSMODE_DESC_BIGENDIAN 0x00100000L /* 21041 only */ +#define TULIP_BUSMODE_READMULTIPLE 0x00200000L /* */ + +#define TULIP_REG_CFDA 0x40 +#define TULIP_CFDA_SLEEP 0x80000000L +#define TULIP_CFDA_SNOOZE 0x40000000L + +#define TULIP_GP_PINSET 0x00000100L +/* + * These are the defintitions used for the DEC 21140 + * evaluation board. + */ +#define TULIP_GP_EB_PINS 0x0000001F /* General Purpose Pin directions */ +#define TULIP_GP_EB_OK10 0x00000080 /* 10 Mb/sec Signal Detect gep<7> */ +#define TULIP_GP_EB_OK100 0x00000040 /* 100 Mb/sec Signal Detect gep<6> */ +#define TULIP_GP_EB_INIT 0x0000000B /* No loopback --- point-to-point */ + +/* + * These are the defintitions used for the SMC9332 (21140) board. + */ +#define TULIP_GP_SMC_9332_PINS 0x0000003F /* General Purpose Pin directions */ +#define TULIP_GP_SMC_9332_OK10 0x00000080 /* 10 Mb/sec Signal Detect gep<7> */ +#define TULIP_GP_SMC_9332_OK100 0x00000040 /* 100 Mb/sec Signal Detect gep<6> */ +#define TULIP_GP_SMC_9332_INIT 0x00000009 /* No loopback --- point-to-point */ + +#define TULIP_OUI_SMC_0 0x00 +#define TULIP_OUI_SMC_1 0x00 +#define TULIP_OUI_SMC_2 0xC0 + +/* + * There are the definitions used for the DEC DE500 + * 10/100 family of boards + */ +#define TULIP_GP_DE500_PINS 0x0000001FL +#define TULIP_GP_DE500_LINK_PASS 0x00000080L +#define TULIP_GP_DE500_SYM_LINK 0x00000040L +#define TULIP_GP_DE500_SIGNAL_DETECT 0x00000020L +#define TULIP_GP_DE500_PHY_RESET 0x00000010L +#define TULIP_GP_DE500_HALFDUPLEX 0x00000008L +#define TULIP_GP_DE500_PHY_LOOPBACK 0x00000004L +#define TULIP_GP_DE500_FORCE_LED 0x00000002L +#define TULIP_GP_DE500_FORCE_100 0x00000001L + +/* + * These are the defintitions used for the Cogent EM100 + * 21140 board. + */ +#define TULIP_GP_EM100_PINS 0x0000003F /* General Purpose Pin directions */ +#define TULIP_GP_EM100_INIT 0x00000009 /* No loopback --- point-to-point */ +#define TULIP_OUI_COGENT_0 0x00 +#define TULIP_OUI_COGENT_1 0x00 +#define TULIP_OUI_COGENT_2 0x92 +#define TULIP_COGENT_EM100TX_ID 0x12 +#define TULIP_COGENT_EM100FX_ID 0x15 + + +/* + * These are the defintitions used for the Znyx ZX342 + * 10/100 board + */ +#define TULIP_OUI_ZNYX_0 0x00 +#define TULIP_OUI_ZNYX_1 0xC0 +#define TULIP_OUI_ZNYX_2 0x95 + +#define TULIP_ZNYX_ID_ZX312 0x0602 +#define TULIP_ZNYX_ID_ZX312T 0x0622 +#define TULIP_ZNYX_ID_ZX314_INTA 0x0701 +#define TULIP_ZNYX_ID_ZX314 0x0711 +#define TULIP_ZNYX_ID_ZX315_INTA 0x0801 +#define TULIP_ZNYX_ID_ZX315 0x0811 +#define TULIP_ZNYX_ID_ZX342 0x0901 +#define TULIP_ZNYX_ID_ZX342B 0x0921 +#define TULIP_ZNYX_ID_ZX342_X3 0x0902 +#define TULIP_ZNYX_ID_ZX342_X4 0x0903 +#define TULIP_ZNYX_ID_ZX344 0x0A01 +#define TULIP_ZNYX_ID_ZX351 0x0B01 +#define TULIP_ZNYX_ID_ZX345 0x0C01 +#define TULIP_ZNYX_ID_ZX311 0x0D01 +#define TULIP_ZNYX_ID_ZX346 0x0E01 + +#define TULIP_GP_ZX34X_PINS 0x0000001F /* General Purpose Pin directions */ +#define TULIP_GP_ZX344_PINS 0x0000000B /* General Purpose Pin directions */ +#define TULIP_GP_ZX345_PINS 0x00000003 /* General Purpose Pin directions */ +#define TULIP_GP_ZX346_PINS 0x00000043 /* General Purpose Pin directions */ +#define TULIP_GP_ZX34X_LNKFAIL 0x00000080 /* 10Mb/s Link Failure */ +#define TULIP_GP_ZX34X_SYMDET 0x00000040 /* 100Mb/s Symbol Detect */ +#define TULIP_GP_ZX345_PHYACT 0x00000040 /* PHY Activity */ +#define TULIP_GP_ZX34X_SIGDET 0x00000020 /* 100Mb/s Signal Detect */ +#define TULIP_GP_ZX346_AUTONEG_ENABLED 0x00000020 /* 802.3u autoneg enabled */ +#define TULIP_GP_ZX342_COLENA 0x00000008 /* 10t Ext LB */ +#define TULIP_GP_ZX344_ROTINT 0x00000008 /* PPB IRQ rotation */ +#define TULIP_GP_ZX345_SPEED10 0x00000008 /* 10Mb speed detect */ +#define TULIP_GP_ZX346_SPEED100 0x00000008 /* 100Mb speed detect */ +#define TULIP_GP_ZX34X_NCOLENA 0x00000004 /* 10t Int LB */ +#define TULIP_GP_ZX34X_RXMATCH 0x00000004 /* RX Match */ +#define TULIP_GP_ZX346_FULLDUPLEX 0x00000004 /* Full Duplex Sensed */ +#define TULIP_GP_ZX34X_LB102 0x00000002 /* 100tx twister LB */ +#define TULIP_GP_ZX34X_NLB101 0x00000001 /* PDT/PDR LB */ +#define TULIP_GP_ZX34X_INIT 0x00000009 + +/* + * Compex's OUI. We need to twiddle a bit on their 21041 card. + */ +#define TULIP_OUI_COMPEX_0 0x00 +#define TULIP_OUI_COMPEX_1 0x80 +#define TULIP_OUI_COMPEX_2 0x48 +#define TULIP_21041_COMPEX_XREGDATA 1 + +/* + * Asante's OUI and stuff... + */ +#define TULIP_OUI_ASANTE_0 0x00 +#define TULIP_OUI_ASANTE_1 0x00 +#define TULIP_OUI_ASANTE_2 0x94 +#define TULIP_GP_ASANTE_PINS 0x000000bf /* GP pin config */ +#define TULIP_GP_ASANTE_PHYRESET 0x00000008 /* Reset PHY */ + +/* + * SROM definitions for the 21140 and 21041. + */ +#define SROMXREG 0x0400 +#define SROMSEL 0x0800 +#define SROMRD 0x4000 +#define SROMWR 0x2000 +#define SROMDIN 0x0008 +#define SROMDOUT 0x0004 +#define SROMDOUTON 0x0004 +#define SROMDOUTOFF 0x0004 +#define SROMCLKON 0x0002 +#define SROMCLKOFF 0x0002 +#define SROMCSON 0x0001 +#define SROMCSOFF 0x0001 +#define SROMCS 0x0001 + +#define SROMCMD_MODE 4 +#define SROMCMD_WR 5 +#define SROMCMD_RD 6 + +#define SROM_BITWIDTH 6 + +/* + * MII Definitions for the 21041 and 21140/21140A/21142 + */ +#define MII_PREAMBLE (~0) +#define MII_TEST 0xAAAAAAAA +#define MII_RDCMD 0xF6 /* 1111.0110 */ +#define MII_WRCMD 0xF5 /* 1111.0101 */ +#define MII_DIN 0x00080000 +#define MII_RD 0x00040000 +#define MII_WR 0x00000000 +#define MII_DOUT 0x00020000 +#define MII_CLK 0x00010000 +#define MII_CLKON MII_CLK +#define MII_CLKOFF MII_CLK + +#define PHYREG_CONTROL 0 +#define PHYREG_STATUS 1 +#define PHYREG_IDLOW 2 +#define PHYREG_IDHIGH 3 +#define PHYREG_AUTONEG_ADVERTISEMENT 4 +#define PHYREG_AUTONEG_ABILITIES 5 +#define PHYREG_AUTONEG_EXPANSION 6 +#define PHYREG_AUTONEG_NEXTPAGE 7 + +#define PHYSTS_100BASET4 0x8000 +#define PHYSTS_100BASETX_FD 0x4000 +#define PHYSTS_100BASETX 0x2000 +#define PHYSTS_10BASET_FD 0x1000 +#define PHYSTS_10BASET 0x0800 +#define PHYSTS_AUTONEG_DONE 0x0020 +#define PHYSTS_REMOTE_FAULT 0x0010 +#define PHYSTS_CAN_AUTONEG 0x0008 +#define PHYSTS_LINK_UP 0x0004 +#define PHYSTS_JABBER_DETECT 0x0002 +#define PHYSTS_EXTENDED_REGS 0x0001 + +#define PHYCTL_RESET 0x8000 +#define PHYCTL_SELECT_100MB 0x2000 +#define PHYCTL_AUTONEG_ENABLE 0x1000 +#define PHYCTL_ISOLATE 0x0400 +#define PHYCTL_AUTONEG_RESTART 0x0200 +#define PHYCTL_FULL_DUPLEX 0x0100 + + +#define MII_RD 0x00040000 +#define MII_WR 0x00000000 +#define MII_DIN 0x00080000 +#define MII_DOUT 0x00020000 +#define MII_DOUTON MII_DOUT +#define MII_DOUTOFF MII_DOUT +#define MII_CLK 0x00010000 +#define MII_CLKON MII_CLK +#define MII_CLKOFF MII_CLK + +/* + * Definitions for the DE425. + */ +#define DE425_CFID 0x08 /* Configuration Id */ +#define DE425_CFCS 0x0C /* Configuration Command-Status */ +#define DE425_CFRV 0x18 /* Configuration Revision */ +#define DE425_CFLT 0x1C /* Configuration Latency Timer */ +#define DE425_CBIO 0x28 /* Configuration Base IO Address */ +#define DE425_CFDA 0x2C /* Configuration Driver Area */ +#define DE425_ENETROM_OFFSET 0xC90 /* Offset in I/O space for ENETROM */ +#define DE425_CFG0 0xC88 /* IRQ register */ +#define DE425_EISAID 0x10a34250 /* EISA device id */ +#define DE425_EISA_IOSIZE 0x100 + +#define DEC_VENDORID 0x1011 +#define CHIPID_21040 0x0002 +#define CHIPID_21140 0x0009 +#define CHIPID_21041 0x0014 +#define CHIPID_21142 0x0019 +#define PCI_VENDORID(x) ((x) & 0xFFFF) +#define PCI_CHIPID(x) (((x) >> 16) & 0xFFFF) + +/* + * Generic SROM Format + * + * + */ + +typedef struct { + u_int8_t sh_idbuf[18]; + u_int8_t sh_version; + u_int8_t sh_adapter_count; + u_int8_t sh_ieee802_address[6]; +} tulip_srom_header_t; + +typedef struct { + u_int8_t sai_device; + u_int8_t sai_leaf_offset_lowbyte; + u_int8_t sai_leaf_offset_highbyte; +} tulip_srom_adapter_info_t; + +typedef enum { + TULIP_SROM_CONNTYPE_10BASET =0x0000, + TULIP_SROM_CONNTYPE_BNC =0x0001, + TULIP_SROM_CONNTYPE_AUI =0x0002, + TULIP_SROM_CONNTYPE_100BASETX =0x0003, + TULIP_SROM_CONNTYPE_100BASET4 =0x0006, + TULIP_SROM_CONNTYPE_100BASEFX =0x0007, + TULIP_SROM_CONNTYPE_MII_10BASET =0x0009, + TULIP_SROM_CONNTYPE_MII_100BASETX =0x000D, + TULIP_SROM_CONNTYPE_MII_100BASET4 =0x000F, + TULIP_SROM_CONNTYPE_MII_100BASEFX =0x0010, + TULIP_SROM_CONNTYPE_10BASET_NWAY =0x0100, + TULIP_SROM_CONNTYPE_10BASET_FD =0x0204, + TULIP_SROM_CONNTYPE_MII_10BASET_FD =0x020A, + TULIP_SROM_CONNTYPE_100BASETX_FD =0x020E, + TULIP_SROM_CONNTYPE_MII_100BASETX_FD =0x0211, + TULIP_SROM_CONNTYPE_10BASET_NOLINKPASS =0x0400, + TULIP_SROM_CONNTYPE_AUTOSENSE =0x0800, + TULIP_SROM_CONNTYPE_AUTOSENSE_POWERUP =0x8800, + TULIP_SROM_CONNTYPE_AUTOSENSE_NWAY =0x9000, + TULIP_SROM_CONNTYPE_NOT_USED =0xFFFF +} tulip_srom_connection_t; + +typedef enum { + TULIP_SROM_MEDIA_10BASET =0x0000, + TULIP_SROM_MEDIA_BNC =0x0001, + TULIP_SROM_MEDIA_AUI =0x0002, + TULIP_SROM_MEDIA_100BASETX =0x0003, + TULIP_SROM_MEDIA_10BASET_FD =0x0004, + TULIP_SROM_MEDIA_100BASETX_FD =0x0005, + TULIP_SROM_MEDIA_100BASET4 =0x0006, + TULIP_SROM_MEDIA_100BASEFX =0x0007, + TULIP_SROM_MEDIA_100BASEFX_FD =0x0008 +} tulip_srom_media_t; + +#define TULIP_SROM_21041_EXTENDED 0x40 + +#define TULIP_SROM_2114X_NOINDICATOR 0x8000 +#define TULIP_SROM_2114X_DEFAULT 0x4000 +#define TULIP_SROM_2114X_POLARITY 0x0080 +#define TULIP_SROM_2114X_CMDBITS(n) (((n) & 0x0071) << 18) +#define TULIP_SROM_2114X_BITPOS(b) (1 << (((b) & 0x0E) >> 1)) + + + +#endif /* !defined(_DC21040_H) */ diff --git a/usr.sbin/natd/HISTORY b/usr.sbin/natd/HISTORY new file mode 100644 index 000000000000..404be4be06d0 --- /dev/null +++ b/usr.sbin/natd/HISTORY @@ -0,0 +1,113 @@ +* Version 0.1 + + Initial version of natd. + +* Version 0.2 + + - Alias address can now be set by giving interface name with + new (-n) command-line option. + + - New Makefile based on bsd.prog.mk. + + - Error messages are written to syslog + after natd has become a daemon. + +* Version 1.0 + + - Support for using only single socket (-p option) + +* Version 1.1 + + - -a option now understands a hostname also. + - -a option no longer dumps core. + - Packet aliasing software upgraded to v. 1.9 + - added long option names (like -address) + +* Version 1.2 + + - Fixed core dump with -port option. + - Added -Wall to CFLAGS and some headers added to natd.c + to get clean compile by Brian Somers [brian@awfulhak.org]. + +* Version 1.3 + + - Aliasing address initialization is delayed until first + packet arrives. This allows natd to start up before + interface address is set. + - SIGTERM is now catched to allow kernel to close + existing connections when system is shutting down. + - SIGHUP is now catched to allow natd to refresh aliasing + address from interface, which might be useful to tun devices. + +* Version 1.4 + + - Changed command line options to be compatible with + command names used in ppp+packetAlias package (which is the + original application using aliasing routines). + + The options which map directly to packet aliasing options are: + + -unregistered_only [yes|no] + -log [yes|no] + -deny_incoming [yes|no] + -use_sockets [yes|no] + -same_ports [yes|no] + + The short option names are the same as in previous + releases. + + - Command line parser rewritten to provide more flexible + way to support new packet aliasing options. + + - Support for natd.cf configuration file has been added. + + - SIGHUP no longer causes problems when running without + interface name option. + + - When using -interface command line option, routing socket + is optionally listened for interface address changes. This + mode is activated by -dynamic option. + + - Directory tree reorganized, alias package is now a library. + + - Manual page written by Brian Somers <brian@awfulhak.org> added. + - README file updated. + +* Version 1.5 + + - Support for sending ICMP 'need fragmentation' messages + when packet size exceeds mtu size of outgoing network interface. + + - ipfw rule example in manual page fixed. + +* Version 1.6 + + - Upgrade to new packet aliasing engine (2.1) + - redirect_port and redirect_address configuration + parameters added. + - It is no longer necessary to quote complex parameter values + in command line. + - Manual page fixed (same_port -> same_ports). + +* Version 1.7 + + - A bug in command-line parsing fixed (it appeared due + to changes made in 1.6). + +* Version 1.8 + + - Fixed problems with -dynamic option. + - Added /var/run/natd.pid + +* Version 1.9 + + - Changes to manual page by + Brian Somers <brian@awfulhak.org> integrated. + - Checksum for incoming packets is always recalculated + for FreeBSD 2.2 and never recalculated for newer + versions. This should fix the problem with wrong + checksum of fragmented packets. + - Buffer space problem found by Sergio Lenzi <lenzi@bsi.com.br> + fixed. Natd now waits with select(2) for buffer space + to become available if write fails. + - Packet aliasing library upgraded to 2.2. diff --git a/usr.sbin/natd/README b/usr.sbin/natd/README new file mode 100644 index 000000000000..6c158d5e4ca1 --- /dev/null +++ b/usr.sbin/natd/README @@ -0,0 +1,53 @@ + + A Network Address Translation Daemon for FreeBSD + + +1. WHAT IS NATD ? + + This is a simple daemon based on FreeBSD divert sockets + which performs network address translation (or masquerading) + for IP packets (see related RFCs 1631 and 1918). + It is based on packet aliasing package (see README.alias) + written by Charles Mott (cmott@srv.net). + + This package works with any network interface (doesn't have + to be ppp). I run it on a computer having two ethernet cards, + one connected to internet and the other one to local network. + +2. GETTING IT RUNNING + + 1) Get FreeBSD 2.2 - I think the divert sockets are + not available on earlier versions, + + 2) Compile this software by executing "make". + + 3) Install the software by executing "make install". + + 4) See man natd for further instructions. + +3. FTP SITES FOR NATD + + This package is available at ftp://ftp.suutari.iki.fi/pub/natd. + +4. AUTHORS + + This program is the result of the efforts of many people + at different times: + + Archie Cobbs <archie@whistle.com> Divert sockets + Charles Mott <cmott@srv.net> Packet aliasing engine + Eivind Eklund <eivind@dimaga.com> Packet aliasing engine + Ari Suutari <suutari@iki.fi> Natd + Brian Somers <brian@awfulhak.org> Manual page, glue and + bunch of good ideas. + + The original package written by Charles Mott + is available at http://www.srv.net/~cmott. + It is described in README.alias. + + Happy Networking - comments and fixes are welcome! + + Ari S. (suutari@iki.fi) + + + diff --git a/usr.sbin/natd/icmp.c b/usr.sbin/natd/icmp.c new file mode 100644 index 000000000000..2018f66128c9 --- /dev/null +++ b/usr.sbin/natd/icmp.c @@ -0,0 +1,113 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <errno.h> +#include <signal.h> + +#include <netdb.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/ip_icmp.h> +#include <machine/in_cksum.h> + +#include <alias.h> + +#include "natd.h" + +int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu) +{ + char icmpBuf[IP_MAXPACKET]; + struct ip* ip; + struct icmp* icmp; + int icmpLen; + int failBytes; + int failHdrLen; + struct sockaddr_in addr; + int wrote; + struct in_addr swap; +/* + * Don't send error if packet is + * not the first fragment. + */ + if (ntohs (failedDgram->ip_off) & ~(IP_MF | IP_DF)) + return 0; +/* + * Dont respond if failed datagram is ICMP. + */ + if (failedDgram->ip_p == IPPROTO_ICMP) + return 0; +/* + * Start building the message. + */ + ip = (struct ip*) icmpBuf; + icmp = (struct icmp*) (icmpBuf + sizeof (struct ip)); +/* + * Complete ICMP part. + */ + icmp->icmp_type = ICMP_UNREACH; + icmp->icmp_code = ICMP_UNREACH_NEEDFRAG; + icmp->icmp_cksum = 0; + icmp->icmp_void = 0; + icmp->icmp_nextmtu = htons (mtu); +/* + * Copy header + 64 bits of original datagram. + */ + failHdrLen = (failedDgram->ip_hl << 2); + failBytes = failedDgram->ip_len - failHdrLen; + if (failBytes > 8) + failBytes = 8; + + failBytes += failHdrLen; + icmpLen = ICMP_MINLEN + failBytes; + + memcpy (&icmp->icmp_ip, failedDgram, failBytes); +/* + * Calculate checksum. + */ + icmp->icmp_cksum = PacketAliasInternetChecksum ((u_short*) icmp, + icmpLen); +/* + * Add IP header using old IP header as template. + */ + memcpy (ip, failedDgram, sizeof (struct ip)); + + ip->ip_v = 4; + ip->ip_hl = 5; + ip->ip_len = htons (sizeof (struct ip) + icmpLen); + ip->ip_p = IPPROTO_ICMP; + ip->ip_tos = 0; + + swap = ip->ip_dst; + ip->ip_dst = ip->ip_src; + ip->ip_src = swap; + + PacketAliasIn ((char*) ip, IP_MAXPACKET); + + addr.sin_family = AF_INET; + addr.sin_addr = ip->ip_dst; + addr.sin_port = 0; +/* + * Put packet into processing queue. + */ + wrote = sendto (sock, + icmp, + icmpLen, + 0, + (struct sockaddr*) &addr, + sizeof addr); + + if (wrote != icmpLen) + Warn ("Cannot send ICMP message."); + + return 1; +} + + diff --git a/usr.sbin/natd/natd.8 b/usr.sbin/natd/natd.8 new file mode 100644 index 000000000000..c38887c7c55c --- /dev/null +++ b/usr.sbin/natd/natd.8 @@ -0,0 +1,381 @@ +.\" manual page [] for natd 1.4 +.Dd 15 April 1997 +.Os FreeBSD +.Dt NATD 8 +.Sh NAME +.Nm natd +.Nd +Network Address Translation Daemon +.Sh SYNOPSIS +.Nm +.Op Fl ldsmvu +.Op Fl permanent_link +.Op Fl dynamic +.Op Fl i Ar inport +.Op Fl o Ar outport +.Op Fl p Ar port +.Op Fl a Ar address +.Op Fl i Ar interface +.Op Fl f Ar configfile + +.Nm +.Op Fl log +.Op Fl deny_incoming +.Op Fl use_sockets +.Op Fl same_ports +.Op Fl verbose +.Op Fl unregistered_only +.Op Fl permanent_link +.Op Fl dynamic +.Op Fl inport Ar inport +.Op Fl outport Ar outport +.Op Fl port Ar port +.Op Fl alias_address Ar address +.Op Fl interface Ar interface +.Op Fl config Ar configfile + +.Sh DESCRIPTION +This program provides a Network Address Translation facility for use +with +.Xr divert 4 +sockets under FreeBSD. Most of the command line options are available +in a single character short form or in a long form. Use of the long +form is encouraged as it makes things clearer to the casual observer. + +.Pp +.Nm Natd +normally runs in the background as a daemon. It is passed raw IP packets +as they travel into and out of the machine, and will possibly change these +before re-injecting them back into the IP packet stream. + +.Pp +.Nm Natd +changes all packets destined for another host so that their source +IP number is that of the current machine. For each packet changed +in this manner, an internal table entry is created to record this +fact. The source port number is also changed to indicate the +table entry applying to the packet. Packets that are received with +a target IP of the current host are checked against this internal +table. If an entry is found, it is used to determine the correct +target IP number and port to place in the packet. + +.Pp +The following command line options are available. +.Bl -tag -width Fl + +.It Fl log | l +Log various aliasing statistics and information to the file +.Pa /var/log/alias.log . +This file is truncated each time natd is started. + +.It Fl deny_incoming | d +Reject packets destined for the current IP number that have no entry +in the internal translation table. + +.It Fl use_sockets | s +Allocate a +.Xr socket 2 +in order to establish an FTP data or IRC DCC send connection. This +option uses more system resources, but guarantees successful connections +when port numbers conflict. + +.It Fl same_ports | m +Try to keep the same port number when altering outgoing packets. +With this option, protocols such as RPC will have a better chance +of working. If it is not possible to maintain the port number, it +will be silently changed as per normal. + +.It Fl verbose | v +Don't call +.Xr fork 2 +or +.Xr daemon 3 +on startup. Instead, stay attached to the controling terminal and +display all packet alterations to the standard output. This option +should only be used for debugging purposes. + +.It Fl unregistered_only | u +Only alter outgoing packets with an unregistered source address. +According to rfc 1918, unregistered source addresses are 10.0.0.0/8, +172.16.0.0/12 and 192.168.0.0/16. + +.It Fl redirect_port Ar linkspec +Redirect incoming connections arriving to given port to another host and port. +Linkspec is of the form + + proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]] + +where proto is either tcp or udp, targetIP is the desired target IP +number, targetPORT is the desired target PORT number, aliasPORT +is the requested PORT number and aliasIP is the aliasing address. +RemoteIP and remotePORT can be used to specify the connection +more accurately if necessary. +For example, the argument + +.Ar tcp inside1:telnet 6666 + +means that tcp packets destined for port 6666 on this machine will +be sent to the telnet port on the inside1 machine. + +.It Fl redirect_address Ar localIP publicIP +Redirect traffic for public IP address to a machine on the local +network. This function is known as "static NAT". Normally static NAT +is useful if your ISP has allocated a small block of IP addresses to you, +but it can even be used in the case of single address: + + redirect_address 10.0.0.8 0.0.0.0 + +The above command would redirect all incoming traffic +to machine 10.0.0.8. + +If several address aliases specify the same public address +as follows + + redirect_address 192.168.0.2 public_addr + redirect_address 192.168.0.3 public_addr + redirect_address 192.168.0.4 public_addr + +the incoming traffic will be directed to the last +translated local address (192.168.0.4), but outgoing +traffice to the first two addresses will still be aliased +to specified public address. + +.It Fl permanent_link Ar linkspec +Create a permanent entry in the internal alias table. Linkspec is +of the form + + proto targetIP:targetPORT sourceIP:sourcePORT aliasPORT + +where proto is either tcp or udp, targetIP is the desired target IP +number, targetPORT is the desired target PORT number, sourceIP and +sourcePORT match the incoming packet, and aliasPORT is the requested +PORT number. Values of zero are considered as wildcards. For example, +the argument + +.Ar tcp inside1:telnet outside1:0 6666 + +means that tcp packets destined for port 6666 on this machine from the +outside1 machine (any port) will be sent to the telnet port on the +inside1 machine. + +New installations are encouraged to use redirect_port instead. + +.It Fl dynamic +If the +.Fl n +or +.Fl interface +option is used, +.Nm natd +will monitor the routing socket for alterations to the +.Ar interface +passed. If the interfaces IP number is changed, +.Nm natd +will dynamically alter its concept of the alias address. + +.It Fl i | inport Ar inport +Read from and write to +.Ar inport , +treating all packets as packets coming into the machine. + +.It Fl o | outport Ar outport +Read from and write to +.Ar outport , +treating all packets as packets going out of the machine. + +.It Fl p | port Ar port +Read from and write to +.Ar port , +distinguishing packets as incoming our outgoing using the rules specified in +.Xr divert 4 . +If +.Ar port +is not numeric, it is searched for in the +.Pa /etc/services +database using the +.Xr getservbyname 3 +function. If this flag is not specified, the divert port named natd will +be used as a default. An example entry in the +.Pa /etc/services +database would be: + + natd 6668/divert # Network Address Translation socket + +Refer to +.Xr services 5 +for further details. + +.It Fl a | alias_address Ar address +Use +.Ar address +as the alias address. If this option is not specified, the +.Fl n +or +.Fl interface +option must be used. + +.It Fl n | interface Ar interface +Use +.Ar interface +to determine the alias address. If there is a possibility that the +IP number associated with +.Ar interface +may change, the +.Fl dynamic +flag should also be used. If this option is not specified, the +.Fl a +or +.Fl alias_address +flag must be used. + +.It Fl f | config Ar configfile +Read configuration from +.Ar configfile . +.Ar Configfile +contains a list of options, one per line in the same form as the +long form of the above command line flags. For example, the line + + alias_address 158.152.17.1 + +would specify an alias address of 158.152.17.1. Options that don't +take an argument are specified with an option of +.Ar yes +or +.Ar no +in the configuration file. For example, the line + + log yes + +is synonomous with +.Fl log . +Empty lines and lines beginning with '#' are ignored. + +.El + +.Sh RUNNING NATD +The following steps are necessary before attempting to run +.Nm natd : + +.Bl -enum +.It +Get FreeBSD version 2.2 or higher. Versions before this do not support +.Xr divert 4 +sockets. + +.It +Build a custom kernel with the following options: + + options IPFIREWALL + options IPDIVERT + +Refer to the handbook for detailed instructions on building a custom +kernel. + +.It +Ensure that your machine is acting as a gateway. This can be done by +specifying the line + + gateway_enable=YES + +in +.Pa /etc/rc.conf , +or using the command + + sysctl -w net.inet.ip.forwarding=1 + +.It +If you wish to use the +.Fl n +or +.Fl interface +flags, make sure that your interface is already configured. If, for +example, you wish to specify tun0 as your +.Ar interface , +and you're using +.Xr ppp 8 +on that interface, you must make sure that you start +.Nm ppp +prior to starting +.Nm natd . + +.It +Create an entry in +.Pa /etc/services : + + natd 6668/divert # Network Address Translation socket + +This gives a default for the +.Fl p +or +.Fl port +flag. + +.El +.Pp +Running +.Nm natd +is fairly straight forward. The line + + natd -interface ed0 + +should suffice in most cases (substituting the correct interface name). Once +.Nm natd +is running, you must ensure that traffic is diverted to natd: + +.Bl -enum +.It +You will need to adjust the +.Pa /etc/rc.firewall +script to taste. If you're not interested in having a firewall, the +following lines will do: + + /sbin/ipfw -f flush + /sbin/ipfw add divert natd all from any to any via ed0 + /sbin/ipfw add pass all from any to any + +The second line depends on your interface (change ed0 as appropriate) +and assumes that you've updated +.Pa /etc/services +with the natd entry as above. If you specify real firewall rules, it's +best to specify line 2 at the start of the script so that +.Nm natd +sees all packets before they are dropped by the firewall. The firewall +rules will be run again on each packet after translation by +.Nm natd , +minus any divert rules. + +.It +Enable your firewall by setting + + firewall=YES + +in +.Pa /etc/rc.conf . +This tells the system startup scripts to run the +.Pa /etc/rc.firewall +script. If you don't wish to reboot now, just run this by hand from the +console. NEVER run this from a virtual session unless you put it into +the background. If you do, you'll lock yourself out after the flush +takes place, and execution of +.Pa /etc/rc.firewall +will stop at this point - blocking all accesses permanently. Running +the script in the background should be enough to prevent this disaster. + +.El + +.Sh SEE ALSO +.Xr socket 2 , +.Xr getservbyname 2 , +.Xr divert 4 , +.Xr services 5 , +.Xr ipfw 8 + +.Sh AUTHORS +This program is the result of the efforts of many people at different +times: + + Divert sockets: Archie Cobbs <archie@whistle.com> + Packet aliasing: Charles Mott <cmott@srv.net> + IRC support & misc additions: Eivind Eklund <eivind@dimaga.com> + Natd: Ari Suutari <suutari@iki.fi> + Glue: Brian Somers <brian@awfulhak.org> diff --git a/usr.sbin/natd/natd.c b/usr.sbin/natd/natd.c new file mode 100644 index 000000000000..13cf6ab0540c --- /dev/null +++ b/usr.sbin/natd/natd.c @@ -0,0 +1,1434 @@ +/* + * natd - Network Address Translation Daemon for FreeBSD. + * + * This software ois provided free of charge, with no + * warranty of any kind, either expressed or implied. + * Use at your own risk. + * + * You may copy, modify and distribute this software (natd.c) freely. + * + * Ari Suutari <suutari@iki.fi> + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <ctype.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <errno.h> +#include <signal.h> + +#include <netdb.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <machine/in_cksum.h> +#include <netinet/tcp.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <net/route.h> +#include <arpa/inet.h> + +#include <syslog.h> +#include <alias.h> + +#include "natd.h" + +/* + * Default values for input and output + * divert socket ports. + */ + +#define DEFAULT_SERVICE "natd" + +/* + * Function prototypes. + */ + +static void DoAliasing (int fd); +static void DaemonMode (); +static void HandleRoutingInfo (int fd); +static void Usage (); +static void PrintPacket (struct ip*); +static void SetAliasAddressFromIfName (char* ifName); +static void InitiateShutdown (); +static void Shutdown (); +static void RefreshAddr (); +static void ParseOption (char* option, char* parms, int cmdLine); +static void ReadConfigFile (char* fileName); +static void SetupPermanentLink (char* parms); +static void SetupPortRedirect (char* parms); +static void SetupAddressRedirect (char* parms); +static void StrToAddr (char* str, struct in_addr* addr); +static int StrToPort (char* str, char* proto); +static int StrToProto (char* str); +static int StrToAddrAndPort (char* str, struct in_addr* addr, char* proto); +static void ParseArgs (int argc, char** argv); +static void FlushPacketBuffer (int fd); + +/* + * Globals. + */ + +static int verbose; +static int background; +static int running; +static int assignAliasAddr; +static char* ifName; +static int ifIndex; +static int inPort; +static int outPort; +static int inOutPort; +static struct in_addr aliasAddr; +static int dynamicMode; +static int ifMTU; +static int aliasOverhead; +static int icmpSock; +static char packetBuf[IP_MAXPACKET]; +static int packetLen; +static struct sockaddr_in packetAddr; +static int packetSock; + +int main (int argc, char** argv) +{ + int divertIn; + int divertOut; + int divertInOut; + int routeSock; + struct sockaddr_in addr; + fd_set readMask; + fd_set writeMask; + int fdMax; +/* + * Initialize packet aliasing software. + * Done already here to be able to alter option bits + * during command line and configuration file processing. + */ + PacketAliasInit (); +/* + * Parse options. + */ + inPort = 0; + outPort = 0; + verbose = 0; + inOutPort = 0; + ifName = NULL; + ifMTU = -1; + background = 0; + running = 1; + assignAliasAddr = 0; + aliasAddr.s_addr = INADDR_NONE; + aliasOverhead = 12; + dynamicMode = 0; +/* + * Mark packet buffer empty. + */ + packetSock = -1; + + ParseArgs (argc, argv); +/* + * Check that valid aliasing address has been given. + */ + if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL) { + + fprintf (stderr, "Aliasing address not given.\n"); + exit (1); + } + + if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL) { + + fprintf (stderr, "Both alias address and interface name " + "are not allowed.\n"); + exit (1); + } +/* + * Check that valid port number is known. + */ + if (inPort != 0 || outPort != 0) + if (inPort == 0 || outPort == 0) { + + fprintf (stderr, "Both input and output ports" + " are required.\n"); + exit (1); + } + + if (inPort == 0 && outPort == 0 && inOutPort == 0) + ParseOption ("port", DEFAULT_SERVICE, 0); + +/* + * Create divert sockets. Use only one socket if -p was specified + * on command line. Otherwise, create separate sockets for + * outgoing and incoming connnections. + */ + if (inOutPort) { + + divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); + if (divertInOut == -1) + Quit ("Unable to create divert socket."); + + divertIn = -1; + divertOut = -1; +/* + * Bind socket. + */ + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = inOutPort; + + if (bind (divertInOut, + (struct sockaddr*) &addr, + sizeof addr) == -1) + Quit ("Unable to bind divert socket."); + } + else { + + divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); + if (divertIn == -1) + Quit ("Unable to create incoming divert socket."); + + divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); + if (divertOut == -1) + Quit ("Unable to create outgoing divert socket."); + + divertInOut = -1; + +/* + * Bind divert sockets. + */ + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = inPort; + + if (bind (divertIn, + (struct sockaddr*) &addr, + sizeof addr) == -1) + Quit ("Unable to bind incoming divert socket."); + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = outPort; + + if (bind (divertOut, + (struct sockaddr*) &addr, + sizeof addr) == -1) + Quit ("Unable to bind outgoing divert socket."); + } +/* + * Create routing socket if interface name specified. + */ + if (ifName && dynamicMode) { + + routeSock = socket (PF_ROUTE, SOCK_RAW, 0); + if (routeSock == -1) + Quit ("Unable to create routing info socket."); + } + else + routeSock = -1; +/* + * Create socket for sending ICMP messages. + */ + icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (icmpSock == -1) + Quit ("Unable to create ICMP socket."); +/* + * Become a daemon unless verbose mode was requested. + */ + if (!verbose) + DaemonMode (); +/* + * Catch signals to manage shutdown and + * refresh of interface address. + */ + signal (SIGTERM, InitiateShutdown); + signal (SIGHUP, RefreshAddr); +/* + * Set alias address if it has been given. + */ + if (aliasAddr.s_addr != INADDR_NONE) + PacketAliasSetAddress (aliasAddr); + +/* + * We need largest descriptor number for select. + */ + + fdMax = -1; + + if (divertIn > fdMax) + fdMax = divertIn; + + if (divertOut > fdMax) + fdMax = divertOut; + + if (divertInOut > fdMax) + fdMax = divertInOut; + + if (routeSock > fdMax) + fdMax = routeSock; + + while (running) { + + if (divertInOut != -1 && !ifName && packetSock == -1) { +/* + * When using only one socket, just call + * DoAliasing repeatedly to process packets. + */ + DoAliasing (divertInOut); + continue; + } +/* + * Build read mask from socket descriptors to select. + */ + FD_ZERO (&readMask); + FD_ZERO (&writeMask); + +/* + * If there is unsent packet in buffer, use select + * to check when socket comes writable again. + */ + if (packetSock != -1) { + + FD_SET (packetSock, &writeMask); + } + else { +/* + * No unsent packet exists - safe to check if + * new ones are available. + */ + if (divertIn != -1) + FD_SET (divertIn, &readMask); + + if (divertOut != -1) + FD_SET (divertOut, &readMask); + + if (divertInOut != -1) + FD_SET (divertInOut, &readMask); + } +/* + * Routing info is processed always. + */ + if (routeSock != -1) + FD_SET (routeSock, &readMask); + + if (select (fdMax + 1, + &readMask, + &writeMask, + NULL, + NULL) == -1) { + + if (errno == EINTR) + continue; + + Quit ("Select failed."); + } + + if (packetSock != -1) + if (FD_ISSET (packetSock, &writeMask)) + FlushPacketBuffer (packetSock); + + if (divertIn != -1) + if (FD_ISSET (divertIn, &readMask)) + DoAliasing (divertIn); + + if (divertOut != -1) + if (FD_ISSET (divertOut, &readMask)) + DoAliasing (divertOut); + + if (divertInOut != -1) + if (FD_ISSET (divertInOut, &readMask)) + DoAliasing (divertInOut); + + if (routeSock != -1) + if (FD_ISSET (routeSock, &readMask)) + HandleRoutingInfo (routeSock); + } + + if (background) + unlink (PIDFILE); + + return 0; +} + +static void DaemonMode () +{ + FILE* pidFile; + + daemon (0, 0); + background = 1; + + pidFile = fopen (PIDFILE, "w"); + if (pidFile) { + + fprintf (pidFile, "%d\n", getpid ()); + fclose (pidFile); + } +} + +static void ParseArgs (int argc, char** argv) +{ + int arg; + char* parm; + char* opt; + char parmBuf[256]; + + for (arg = 1; arg < argc; arg++) { + + opt = argv[arg]; + if (*opt != '-') { + + fprintf (stderr, "Invalid option %s.\n", opt); + Usage (); + } + + parm = NULL; + parmBuf[0] = '\0'; + + while (arg < argc - 1) { + + if (argv[arg + 1][0] == '-') + break; + + if (parm) + strcat (parmBuf, " "); + + ++arg; + parm = parmBuf; + strcat (parmBuf, argv[arg]); + } + + ParseOption (opt + 1, parm, 1); + } +} + +static void DoAliasing (int fd) +{ + int bytes; + int origBytes; + int addrSize; + struct ip* ip; + + if (assignAliasAddr) { + + SetAliasAddressFromIfName (ifName); + assignAliasAddr = 0; + } +/* + * Get packet from socket. + */ + addrSize = sizeof packetAddr; + origBytes = recvfrom (fd, + packetBuf, + sizeof packetBuf, + 0, + (struct sockaddr*) &packetAddr, + &addrSize); + + if (origBytes == -1) { + + if (errno != EINTR) + Warn ("Read from divert socket failed."); + + return; + } +/* + * This is a IP packet. + */ + ip = (struct ip*) packetBuf; + + if (verbose) { + +/* + * Print packet direction and protocol type. + */ + + if (packetAddr.sin_addr.s_addr == INADDR_ANY) + printf ("Out "); + else + printf ("In "); + + switch (ip->ip_p) { + case IPPROTO_TCP: + printf ("[TCP] "); + break; + + case IPPROTO_UDP: + printf ("[UDP] "); + break; + + case IPPROTO_ICMP: + printf ("[ICMP] "); + break; + + default: + printf ("[?] "); + break; + } +/* + * Print addresses. + */ + PrintPacket (ip); + } + + if (packetAddr.sin_addr.s_addr == INADDR_ANY) { +/* + * Outgoing packets. Do aliasing. + */ + PacketAliasOut (packetBuf, IP_MAXPACKET); + } + else { +/* + * Do aliasing. + */ + PacketAliasIn (packetBuf, IP_MAXPACKET); + } +/* + * Length might have changed during aliasing. + */ + bytes = ntohs (ip->ip_len); +/* + * Update alias overhead size for outgoing packets. + */ + if (packetAddr.sin_addr.s_addr == INADDR_ANY && + bytes - origBytes > aliasOverhead) + aliasOverhead = bytes - origBytes; + + if (verbose) { + +/* + * Print addresses after aliasing. + */ + printf (" aliased to\n"); + printf (" "); + PrintPacket (ip); + printf ("\n"); + } + + packetLen = bytes; + packetSock = fd; + FlushPacketBuffer (fd); +} + +static void FlushPacketBuffer (int fd) +{ + int wrote; + char msgBuf[80]; +/* + * Put packet back for processing. + */ + wrote = sendto (fd, + packetBuf, + packetLen, + 0, + (struct sockaddr*) &packetAddr, + sizeof packetAddr); + + if (wrote != packetLen) { +/* + * If buffer space is not available, + * just return. Main loop will take care of + * retrying send when space becomes available. + */ + if (errno == ENOBUFS) + return; + + if (errno == EMSGSIZE) { + + if (packetAddr.sin_addr.s_addr == INADDR_ANY && + ifMTU != -1) + SendNeedFragIcmp (icmpSock, + (struct ip*) packetBuf, + ifMTU - aliasOverhead); + } + else { + + sprintf (msgBuf, "Failed to write packet back."); + Warn (msgBuf); + } + } + + packetSock = -1; +} + +static void HandleRoutingInfo (int fd) +{ + int bytes; + struct if_msghdr ifMsg; +/* + * Get packet from socket. + */ + bytes = read (fd, &ifMsg, sizeof ifMsg); + if (bytes == -1) { + + Warn ("Read from routing socket failed."); + return; + } + + if (ifMsg.ifm_version != RTM_VERSION) { + + Warn ("Unexpected packet read from routing socket."); + return; + } + + if (verbose) + printf ("Routing message %X received.\n", ifMsg.ifm_type); + + if (ifMsg.ifm_type != RTM_NEWADDR) + return; + + if (verbose && ifMsg.ifm_index == ifIndex) + printf ("Interface address has changed.\n"); + + if (ifMsg.ifm_index == ifIndex) + assignAliasAddr = 1; +} + +static void PrintPacket (struct ip* ip) +{ + struct tcphdr* tcphdr; + + if (ip->ip_p == IPPROTO_TCP) + tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2)); + else + tcphdr = NULL; + + printf ("%s", inet_ntoa (ip->ip_src)); + if (tcphdr) + printf (":%d", ntohs (tcphdr->th_sport)); + + printf (" -> "); + printf ("%s", inet_ntoa (ip->ip_dst)); + if (tcphdr) + printf (":%d", ntohs (tcphdr->th_dport)); +} + +static void SetAliasAddressFromIfName (char* ifName) +{ + struct ifconf cf; + struct ifreq buf[32]; + char msg[80]; + struct ifreq* ifPtr; + int extra; + int helperSock; + int bytes; + struct sockaddr_in* addr; + int found; + struct ifreq req; + char last[10]; +/* + * Create a dummy socket to access interface information. + */ + helperSock = socket (AF_INET, SOCK_DGRAM, 0); + if (helperSock == -1) { + + Quit ("Failed to create helper socket."); + exit (1); + } + + cf.ifc_len = sizeof (buf); + cf.ifc_req = buf; +/* + * Get interface data. + */ + if (ioctl (helperSock, SIOCGIFCONF, &cf) == -1) { + + Quit ("Ioctl SIOCGIFCONF failed."); + exit (1); + } + + ifIndex = 0; + ifPtr = buf; + bytes = cf.ifc_len; + found = 0; + last[0] = '\0'; +/* + * Loop through interfaces until one with + * given name is found. This is done to + * find correct interface index for routing + * message processing. + */ + while (bytes) { + + if (ifPtr->ifr_addr.sa_family == AF_INET && + !strcmp (ifPtr->ifr_name, ifName)) { + + found = 1; + break; + } + + if (strcmp (last, ifPtr->ifr_name)) { + + strcpy (last, ifPtr->ifr_name); + ++ifIndex; + } + + extra = ifPtr->ifr_addr.sa_len - sizeof (struct sockaddr); + + ifPtr++; + ifPtr = (struct ifreq*) ((char*) ifPtr + extra); + bytes -= sizeof (struct ifreq) + extra; + } + + if (!found) { + + close (helperSock); + sprintf (msg, "Unknown interface name %s.\n", ifName); + Quit (msg); + } +/* + * Get MTU size. + */ + strcpy (req.ifr_name, ifName); + + if (ioctl (helperSock, SIOCGIFMTU, &req) == -1) + Quit ("Cannot get interface mtu size."); + + ifMTU = req.ifr_mtu; +/* + * Get interface address. + */ + if (ioctl (helperSock, SIOCGIFADDR, &req) == -1) + Quit ("Cannot get interface address."); + + addr = (struct sockaddr_in*) &req.ifr_addr; + SetPacketAliasAddress (addr->sin_addr); + syslog (LOG_INFO, "Aliasing to %s, mtu %d bytes", + inet_ntoa (addr->sin_addr), + ifMTU); + + close (helperSock); +} + +void Quit (char* msg) +{ + Warn (msg); + exit (1); +} + +void Warn (char* msg) +{ + if (background) + syslog (LOG_ALERT, "%s (%m)", msg); + else + perror (msg); +} + +static void RefreshAddr () +{ + signal (SIGHUP, RefreshAddr); + if (ifName) + assignAliasAddr = 1; +} + +static void InitiateShutdown () +{ +/* + * Start timer to allow kernel gracefully + * shutdown existing connections when system + * is shut down. + */ + signal (SIGALRM, Shutdown); + alarm (10); +} + +static void Shutdown () +{ + running = 0; +} + +/* + * Different options recognized by this program. + */ + +enum Option { + + PacketAliasOption, + Verbose, + InPort, + OutPort, + Port, + AliasAddress, + InterfaceName, + PermanentLink, + RedirectPort, + RedirectAddress, + ConfigFile, + DynamicMode +}; + +enum Param { + + YesNo, + Numeric, + String, + None, + Address, + Service +}; + +/* + * Option information structure (used by ParseOption). + */ + +struct OptionInfo { + + enum Option type; + int packetAliasOpt; + enum Param parm; + char* parmDescription; + char* description; + char* name; + char* shortName; +}; + +/* + * Table of known options. + */ + +static struct OptionInfo optionTable[] = { + + { PacketAliasOption, + PKT_ALIAS_UNREGISTERED_ONLY, + YesNo, + "[yes|no]", + "alias only unregistered addresses", + "unregistered_only", + "u" }, + + { PacketAliasOption, + PKT_ALIAS_LOG, + YesNo, + "[yes|no]", + "enable logging", + "log", + "l" }, + + { PacketAliasOption, + PKT_ALIAS_DENY_INCOMING, + YesNo, + "[yes|no]", + "allow incoming connections", + "deny_incoming", + "d" }, + + { PacketAliasOption, + PKT_ALIAS_USE_SOCKETS, + YesNo, + "[yes|no]", + "use sockets to inhibit port conflict", + "use_sockets", + "s" }, + + { PacketAliasOption, + PKT_ALIAS_SAME_PORTS, + YesNo, + "[yes|no]", + "try to keep original port numbers for connections", + "same_ports", + "m" }, + + { Verbose, + 0, + YesNo, + "[yes|no]", + "verbose mode, dump packet information", + "verbose", + "v" }, + + { DynamicMode, + 0, + YesNo, + "[yes|no]", + "dynamic mode, automatically detect interface address changes", + "dynamic", + NULL }, + + { InPort, + 0, + Service, + "number|service_name", + "set port for incoming packets", + "in_port", + "i" }, + + { OutPort, + 0, + Service, + "number|service_name", + "set port for outgoing packets", + "out_port", + "o" }, + + { Port, + 0, + Service, + "number|service_name", + "set port (defaults to natd/divert)", + "port", + "p" }, + + { AliasAddress, + 0, + Address, + "x.x.x.x", + "address to use for aliasing", + "alias_address", + "a" }, + + { InterfaceName, + 0, + String, + "network_if_name", + "take aliasing address from interface", + "interface", + "n" }, + + { PermanentLink, + 0, + String, + "tcp|udp src:port dst:port alias", + "define permanent link for incoming connection", + "permanent_link", + NULL }, + + { RedirectPort, + 0, + String, + "tcp|udp local_addr:local_port [public_addr:]public_port" + " [remote_addr[:remote_port]]", + "redirect a port for incoming traffic", + "redirect_port", + NULL }, + + { RedirectAddress, + 0, + String, + "local_addr public_addr", + "define mapping between local and public addresses", + "redirect_address", + NULL }, + + { ConfigFile, + 0, + String, + "file_name", + "read options from configuration file", + "config", + "f" } +}; + +static void ParseOption (char* option, char* parms, int cmdLine) +{ + int i; + struct OptionInfo* info; + int yesNoValue; + int aliasValue; + int numValue; + char* strValue; + struct in_addr addrValue; + int max; + char* end; +/* + * Find option from table. + */ + max = sizeof (optionTable) / sizeof (struct OptionInfo); + for (i = 0, info = optionTable; i < max; i++, info++) { + + if (!strcmp (info->name, option)) + break; + + if (info->shortName) + if (!strcmp (info->shortName, option)) + break; + } + + if (i >= max) { + + fprintf (stderr, "Unknown option %s.\n", option); + Usage (); + } + + yesNoValue = 0; + numValue = 0; + strValue = NULL; +/* + * Check parameters. + */ + switch (info->parm) { + case YesNo: + if (!parms) + parms = "yes"; + + if (!strcmp (parms, "yes")) + yesNoValue = 1; + else + if (!strcmp (parms, "no")) + yesNoValue = 0; + else { + + fprintf (stderr, "%s needs yes/no parameter.\n", + option); + exit (1); + } + break; + + case Service: + if (!parms) { + + fprintf (stderr, "%s needs service name or " + "port number parameter.\n", + option); + exit (1); + } + + numValue = StrToPort (parms, "divert"); + break; + + case Numeric: + if (parms) + numValue = strtol (parms, &end, 10); + else + end = parms; + + if (end == parms) { + + fprintf (stderr, "%s needs numeric parameter.\n", + option); + exit (1); + } + break; + + case String: + strValue = parms; + if (!strValue) { + + fprintf (stderr, "%s needs parameter.\n", + option); + exit (1); + } + break; + + case None: + if (parms) { + + fprintf (stderr, "%s does not take parameters.\n", + option); + exit (1); + } + break; + + case Address: + if (!parms) { + + fprintf (stderr, "%s needs address/host parameter.\n", + option); + exit (1); + } + + StrToAddr (parms, &addrValue); + break; + } + + switch (info->type) { + case PacketAliasOption: + + aliasValue = yesNoValue ? info->packetAliasOpt : 0; + PacketAliasSetMode (aliasValue, info->packetAliasOpt); + break; + + case Verbose: + verbose = yesNoValue; + break; + + case DynamicMode: + dynamicMode = yesNoValue; + break; + + case InPort: + inPort = numValue; + break; + + case OutPort: + outPort = numValue; + break; + + case Port: + inOutPort = numValue; + break; + + case AliasAddress: + memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr)); + break; + + case PermanentLink: + SetupPermanentLink (strValue); + break; + + case RedirectPort: + SetupPortRedirect (strValue); + break; + + case RedirectAddress: + SetupAddressRedirect (strValue); + break; + + case InterfaceName: + if (ifName) + free (ifName); + + ifName = strdup (strValue); + assignAliasAddr = 1; + break; + + case ConfigFile: + ReadConfigFile (strValue); + break; + } +} + +void ReadConfigFile (char* fileName) +{ + FILE* file; + char buf[128]; + char* ptr; + char* option; + + file = fopen (fileName, "r"); + if (!file) { + + sprintf (buf, "Cannot open config file %s.\n", fileName); + Quit (buf); + } + + while (fgets (buf, sizeof (buf), file)) { + + ptr = strchr (buf, '\n'); + if (!ptr) { + + fprintf (stderr, "config line too link: %s\n", buf); + exit (1); + } + + *ptr = '\0'; + if (buf[0] == '#') + continue; + + ptr = buf; +/* + * Skip white space at beginning of line. + */ + while (*ptr && isspace (*ptr)) + ++ptr; + + if (*ptr == '\0') + continue; +/* + * Extract option name. + */ + option = ptr; + while (*ptr && !isspace (*ptr)) + ++ptr; + + if (*ptr != '\0') { + + *ptr = '\0'; + ++ptr; + } +/* + * Skip white space between name and parms. + */ + while (*ptr && isspace (*ptr)) + ++ptr; + + ParseOption (option, *ptr ? ptr : NULL, 0); + } + + fclose (file); +} + +static void Usage () +{ + int i; + int max; + struct OptionInfo* info; + + fprintf (stderr, "Recognized options:\n\n"); + + max = sizeof (optionTable) / sizeof (struct OptionInfo); + for (i = 0, info = optionTable; i < max; i++, info++) { + + fprintf (stderr, "-%-20s %s\n", info->name, + info->parmDescription); + + if (info->shortName) + fprintf (stderr, "-%-20s %s\n", info->shortName, + info->parmDescription); + + fprintf (stderr, " %s\n\n", info->description); + } + + exit (1); +} + +void SetupPermanentLink (char* parms) +{ + char buf[128]; + char* ptr; + struct in_addr srcAddr; + struct in_addr dstAddr; + int srcPort; + int dstPort; + int aliasPort; + int proto; + char* protoName; + + strcpy (buf, parms); +/* + * Extract protocol. + */ + protoName = strtok (buf, " \t"); + if (!protoName) { + + fprintf (stderr, "permanent_link: missing protocol.\n"); + exit (1); + } + + proto = StrToProto (protoName); +/* + * Extract source address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) { + + fprintf (stderr, "permanent_link: missing src address.\n"); + exit (1); + } + + srcPort = StrToAddrAndPort (ptr, &srcAddr, protoName); +/* + * Extract destination address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) { + + fprintf (stderr, "permanent_link: missing dst address.\n"); + exit (1); + } + + dstPort = StrToAddrAndPort (ptr, &dstAddr, protoName); +/* + * Export alias port. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) { + + fprintf (stderr, "permanent_link: missing alias port.\n"); + exit (1); + } + + aliasPort = StrToPort (ptr, protoName); + + PacketAliasPermanentLink (srcAddr, + srcPort, + dstAddr, + dstPort, + aliasPort, + proto); +} + +void SetupPortRedirect (char* parms) +{ + char buf[128]; + char* ptr; + struct in_addr localAddr; + struct in_addr publicAddr; + struct in_addr remoteAddr; + int localPort; + int publicPort; + int remotePort; + int proto; + char* protoName; + char* separator; + + strcpy (buf, parms); +/* + * Extract protocol. + */ + protoName = strtok (buf, " \t"); + if (!protoName) { + + fprintf (stderr, "redirect_port: missing protocol.\n"); + exit (1); + } + + proto = StrToProto (protoName); +/* + * Extract local address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) { + + fprintf (stderr, "redirect_port: missing local address.\n"); + exit (1); + } + + localPort = StrToAddrAndPort (ptr, &localAddr, protoName); +/* + * Extract public port and optinally address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) { + + fprintf (stderr, "redirect_port: missing public port.\n"); + exit (1); + } + + separator = strchr (ptr, ':'); + if (separator) + publicPort = StrToAddrAndPort (ptr, &publicAddr, protoName); + else { + + publicAddr.s_addr = INADDR_ANY; + publicPort = StrToPort (ptr, protoName); + } + +/* + * Extract remote address and optionally port. + */ + ptr = strtok (NULL, " \t"); + if (ptr) { + + + separator = strchr (ptr, ':'); + if (separator) + remotePort = StrToAddrAndPort (ptr, + &remoteAddr, + protoName); + else { + + remotePort = 0; + StrToAddr (ptr, &remoteAddr); + } + } + else { + + remotePort = 0; + remoteAddr.s_addr = INADDR_ANY; + } + + PacketAliasRedirectPort (localAddr, + localPort, + remoteAddr, + remotePort, + publicAddr, + publicPort, + proto); +} + +void SetupAddressRedirect (char* parms) +{ + char buf[128]; + char* ptr; + struct in_addr localAddr; + struct in_addr publicAddr; + + strcpy (buf, parms); +/* + * Extract local address. + */ + ptr = strtok (buf, " \t"); + if (!ptr) { + + fprintf (stderr, "redirect_address: missing local address.\n"); + exit (1); + } + + StrToAddr (ptr, &localAddr); +/* + * Extract public address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) { + + fprintf (stderr, "redirect_address: missing public address.\n"); + exit (1); + } + + StrToAddr (ptr, &publicAddr); + PacketAliasRedirectAddr (localAddr, publicAddr); +} + +void StrToAddr (char* str, struct in_addr* addr) +{ + struct hostent* hp; + + if (inet_aton (str, addr)) + return; + + hp = gethostbyname (str); + if (!hp) { + + fprintf (stderr, "Unknown host %s.\n", str); + exit (1); + } + + memcpy (addr, hp->h_addr, sizeof (struct in_addr)); +} + +int StrToPort (char* str, char* proto) +{ + int port; + struct servent* sp; + char* end; + + port = strtol (str, &end, 10); + if (end != str) + return htons (port); + + sp = getservbyname (str, proto); + if (!sp) { + + fprintf (stderr, "Unknown service %s/%s.\n", + str, proto); + exit (1); + } + + return sp->s_port; +} + +int StrToProto (char* str) +{ + if (!strcmp (str, "tcp")) + return IPPROTO_TCP; + + if (!strcmp (str, "udp")) + return IPPROTO_UDP; + + fprintf (stderr, "Unknown protocol %s. Expected tcp or udp.\n", str); + exit (1); +} + +int StrToAddrAndPort (char* str, struct in_addr* addr, char* proto) +{ + char* ptr; + + ptr = strchr (str, ':'); + if (!ptr) { + + fprintf (stderr, "%s is missing port number.\n", str); + exit (1); + } + + *ptr = '\0'; + ++ptr; + + StrToAddr (str, addr); + return StrToPort (ptr, proto); +} + diff --git a/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4 b/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4 new file mode 100644 index 000000000000..ebce4991def7 --- /dev/null +++ b/usr.sbin/sendmail/cf/ostype/sco-uw-2.1.m4 @@ -0,0 +1,16 @@ +# +# SCO UnixWare 2.1.2 ostype file +# +# Contributed by Christopher Durham <chrisdu@SCO.COM> of SCO. +# +divert(0) +VERSIONID(`@(#)sco-uw-2.1.m4 8.1 (Berkeley) 7/6/97') + +define(`ALIAS_FILE', /usr/lib/mail/aliases)dnl +ifdef(`HELP_FILE',,`define(`HELP_FILE', /usr/ucblib/sendmail.hf)')dnl +ifdef(`STATUS_FILE',,`define(`STATUS_FILE', /usr/ucblib/sendmail.st)')dnl +define(`LOCAL_MAILER_PATH', `/usr/bin/rmail')dnl +define(`LOCAL_MAILER_FLAGS', `fhCEn9')dnl +define(`LOCAL_SHELL_FLAGS', `ehuP')dnl +define(`UUCP_MAILER_ARGS', `uux - -r -a$g -gmedium $h!rmail ($u)')dnl +define(`LOCAL_MAILER_ARGS',`rmail $u')dnl diff --git a/usr.sbin/sendmail/contrib/passwd-to-alias.pl b/usr.sbin/sendmail/contrib/passwd-to-alias.pl new file mode 100644 index 000000000000..05a51b93496f --- /dev/null +++ b/usr.sbin/sendmail/contrib/passwd-to-alias.pl @@ -0,0 +1,30 @@ +#!/bin/perl + +# +# Convert GECOS information in password files to alias syntax. +# +# Contributed by Kari E. Hurtta <Kari.Hurtta@ozone.fmi.fi> +# + +print "# Generated from passwd by $0\n"; + +while (@a = getpwent) { + ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = @a; + + ($fullname = $gcos) =~ s/,.*$//; + + if (!-d $dir || !-x $shell) { + print "$name: root\n"; + } + + $fullname =~ s/\.*[ _]+\.*/./g; + $fullname =~ tr [åäöÅÄÖé] [aaoAAOe]; # <hakan@af.lu.se> 1997-06-15 + if ($fullname =~ /^[a-zA-Z][a-zA-Z-]+(\.[a-zA-Z][a-zA-Z-]+)+$/) { +# if ($fullname =~ /^[a-zA-Z]+(\.[a-zA-Z]+)+$/) { # Kari E. Hurtta + print "$fullname: $name\n"; + } else { + print "# $fullname: $name\n"; + } +}; + +endpwent; diff --git a/usr.sbin/sendmail/src/safefile.c b/usr.sbin/sendmail/src/safefile.c new file mode 100644 index 000000000000..842a09f8ca86 --- /dev/null +++ b/usr.sbin/sendmail/src/safefile.c @@ -0,0 +1,712 @@ +/* + * Copyright (c) 1983, 1995-1997 Eric P. Allman + * Copyright (c) 1988, 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[] = "@(#)safefile.c 8.18 (Berkeley) 8/1/97"; +#endif /* not lint */ + +# include "sendmail.h" +/* +** SAFEFILE -- return true if a file exists and is safe for a user. +** +** Parameters: +** fn -- filename to check. +** uid -- user id to compare against. +** gid -- group id to compare against. +** uname -- user name to compare against (used for group +** sets). +** flags -- modifiers: +** SFF_MUSTOWN -- "uid" must own this file. +** SFF_NOSLINK -- file cannot be a symbolic link. +** mode -- mode bits that must match. +** st -- if set, points to a stat structure that will +** get the stat info for the file. +** +** Returns: +** 0 if fn exists, is owned by uid, and matches mode. +** An errno otherwise. The actual errno is cleared. +** +** Side Effects: +** none. +*/ + +#include <grp.h> + +#ifndef S_IXOTH +# define S_IXOTH (S_IEXEC >> 6) +#endif + +#ifndef S_IXGRP +# define S_IXGRP (S_IEXEC >> 3) +#endif + +#ifndef S_IXUSR +# define S_IXUSR (S_IEXEC) +#endif + +int +safefile(fn, uid, gid, uname, flags, mode, st) + char *fn; + UID_T uid; + GID_T gid; + char *uname; + int flags; + int mode; + struct stat *st; +{ + register char *p; + register struct group *gr = NULL; + int file_errno = 0; + bool checkpath; + struct stat stbuf; + struct stat fstbuf; + char fbuf[MAXPATHLEN + 1]; + + if (tTd(44, 4)) + printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n", + fn, (int) uid, (int) gid, flags, mode); + errno = 0; + if (st == NULL) + st = &fstbuf; + if (strlen(fn) > sizeof fbuf - 1) + { + if (tTd(44, 4)) + printf("\tpathname too long\n"); + return ENAMETOOLONG; + } + strcpy(fbuf, fn); + fn = fbuf; + + /* ignore SFF_SAFEDIRPATH if we are debugging */ + if (RealUid != 0 && RunAsUid == RealUid) + flags &= ~SFF_SAFEDIRPATH; + + /* first check to see if the file exists at all */ +#ifdef HASLSTAT + if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st) + : stat(fn, st)) < 0) +#else + if (stat(fn, st) < 0) +#endif + { + file_errno = errno; + } + else if (bitset(SFF_SETUIDOK, flags) && + !bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) && + S_ISREG(st->st_mode)) + { + /* + ** If final file is setuid, run as the owner of that + ** file. Gotta be careful not to reveal anything too + ** soon here! + */ + +#ifdef SUID_ROOT_FILES_OK + if (bitset(S_ISUID, st->st_mode)) +#else + if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0) +#endif + { + uid = st->st_uid; + uname = NULL; + } +#ifdef SUID_ROOT_FILES_OK + if (bitset(S_ISGID, st->st_mode)) +#else + if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0) +#endif + gid = st->st_gid; + } + + checkpath = !bitset(SFF_NOPATHCHECK, flags) || + (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags)); + if (bitset(SFF_NOWLINK, flags) && !bitset(SFF_SAFEDIRPATH, flags)) + { + int ret; + + /* check the directory */ + p = strrchr(fn, '/'); + if (p == NULL) + { + ret = safedirpath(".", uid, gid, uname, flags|SFF_SAFEDIRPATH); + } + else + { + *p = '\0'; + ret = safedirpath(fn, uid, gid, uname, flags|SFF_SAFEDIRPATH); + *p = '/'; + } + if (ret == 0) + { + /* directory is safe */ + checkpath = FALSE; + } + else + { + /* directory is writable: disallow links */ + flags |= SFF_NOLINK; + } + } + + if (checkpath) + { + int ret; + + p = strrchr(fn, '/'); + if (p == NULL) + { + ret = safedirpath(".", uid, gid, uname, flags); + } + else + { + *p = '\0'; + ret = safedirpath(fn, uid, gid, uname, flags); + *p = '/'; + } + if (ret != 0) + return ret; + } + + /* + ** If the target file doesn't exist, check the directory to + ** ensure that it is writable by this user. + */ + + if (file_errno != 0) + { + int ret = file_errno; + char *dir = fn; + + if (tTd(44, 4)) + printf("\t%s\n", errstring(ret)); + + errno = 0; + if (!bitset(SFF_CREAT, flags) || file_errno != ENOENT) + return ret; + + /* check to see if legal to create the file */ + p = strrchr(dir, '/'); + if (p == NULL) + dir = "."; + else if (p == dir) + dir = "/"; + else + *p = '\0'; + if (stat(dir, &stbuf) >= 0) + { + int md = S_IWRITE|S_IEXEC; + if (stbuf.st_uid != uid) + md >>= 6; + if ((stbuf.st_mode & md) != md) + errno = EACCES; + } + ret = errno; + if (tTd(44, 4)) + printf("\t[final dir %s uid %d mode %lo] %s\n", + dir, (int) stbuf.st_uid, (u_long) stbuf.st_mode, + errstring(ret)); + if (p != NULL) + *p = '/'; + st->st_mode = ST_MODE_NOFILE; + return ret; + } + +#ifdef S_ISLNK + if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[slink mode %o]\tE_SM_NOSLINK\n", + st->st_mode); + return E_SM_NOSLINK; + } +#endif + if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[non-reg mode %o]\tE_SM_REGONLY\n", + st->st_mode); + return E_SM_REGONLY; + } + if (bitset(SFF_NOWFILES, flags) && + bitset(S_IWOTH | (UnsafeGroupWrites ? S_IWGRP : 0), st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[write bits %o]\tE_SM_%cWFILE\n", + st->st_mode, + bitset(S_IWOTH, st->st_mode) ? 'W' : 'G'); + return bitset(S_IWOTH, st->st_mode) ? E_SM_WWFILE : E_SM_GWFILE; + } + if (bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) && + bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode)) + { + if (tTd(44, 4)) + printf("\t[exec bits %o]\tE_SM_ISEXEC]\n", + st->st_mode); + return E_SM_ISEXEC; + } + if (bitset(SFF_NOHLINK, flags) && st->st_nlink != 1) + { + if (tTd(44, 4)) + printf("\t[link count %d]\tE_SM_NOHLINK\n", + st->st_nlink); + return E_SM_NOHLINK; + } + + if (uid == 0 && bitset(SFF_OPENASROOT, flags)) + ; + else if (uid == 0 && !bitset(SFF_ROOTOK, flags)) + mode >>= 6; + else if (st->st_uid != uid) + { + mode >>= 3; + if (st->st_gid == gid) + ; +#ifndef NO_GROUP_SET + else if (uname != NULL && !DontInitGroups && + ((gr != NULL && gr->gr_gid == st->st_gid) || + (gr = getgrgid(st->st_gid)) != NULL)) + { + register char **gp; + + for (gp = gr->gr_mem; *gp != NULL; gp++) + if (strcmp(*gp, uname) == 0) + break; + if (*gp == NULL) + mode >>= 3; + } +#endif + else + mode >>= 3; + } + if (tTd(44, 4)) + printf("\t[uid %d, nlink %d, stat %lo, mode %lo] ", + (int) st->st_uid, (int) st->st_nlink, + (u_long) st->st_mode, (u_long) mode); + if ((st->st_uid == uid || st->st_uid == 0 || + !bitset(SFF_MUSTOWN, flags)) && + (st->st_mode & mode) == mode) + { + if (tTd(44, 4)) + printf("\tOK\n"); + return 0; + } + if (tTd(44, 4)) + printf("\tEACCES\n"); + return EACCES; +} +/* +** SAFEDIRPATH -- check to make sure a path to a directory is safe +** +** Safe means not writable and owned by the right folks. +** +** Parameters: +** fn -- filename to check. +** uid -- user id to compare against. +** gid -- group id to compare against. +** uname -- user name to compare against (used for group +** sets). +** flags -- modifiers: +** SFF_ROOTOK -- ok to use root permissions to open. +** SFF_SAFEDIRPATH -- writable directories are considered +** to be fatal errors. +** +** Returns: +** 0 -- if the directory path is "safe". +** else -- an error number associated with the path. +*/ + +int +safedirpath(fn, uid, gid, uname, flags) + char *fn; + UID_T uid; + GID_T gid; + char *uname; + int flags; +{ + char *p; + register struct group *gr = NULL; + int ret = 0; + struct stat stbuf; + + /* special case root directory */ + if (*fn == '\0') + fn = "/"; + + if (tTd(44, 4)) + printf("safedirpath(%s, uid=%ld, gid=%ld, flags=%x):\n", + fn, (long) uid, (long) gid, flags); + + p = fn; + do + { + if (*p == '\0') + *p = '/'; + p = strchr(++p, '/'); + if (p != NULL) + *p = '\0'; + if (stat(fn, &stbuf) < 0) + { + ret = errno; + break; + } + if ((uid == 0 || bitset(SFF_SAFEDIRPATH, flags)) && + bitset(S_IWGRP|S_IWOTH, stbuf.st_mode)) + { + if (tTd(44, 4)) + printf("\t[dir %s] mode %o\n", + fn, stbuf.st_mode); + if (bitset(SFF_SAFEDIRPATH, flags)) + { + if (bitset(S_IWOTH, stbuf.st_mode)) + ret = E_SM_WWDIR; + else + ret = E_SM_GWDIR; + break; + } + if (Verbose > 1) + message("051 WARNING: writable directory %s", fn); + } + if (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags)) + { + if (bitset(S_IXOTH, stbuf.st_mode)) + continue; + ret = EACCES; + break; + } + if (stbuf.st_uid == uid && + bitset(S_IXUSR, stbuf.st_mode)) + continue; + if (stbuf.st_gid == gid && + bitset(S_IXGRP, stbuf.st_mode)) + continue; +#ifndef NO_GROUP_SET + if (uname != NULL && !DontInitGroups && + ((gr != NULL && gr->gr_gid == stbuf.st_gid) || + (gr = getgrgid(stbuf.st_gid)) != NULL)) + { + register char **gp; + + for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++) + if (strcmp(*gp, uname) == 0) + break; + if (gp != NULL && *gp != NULL && + bitset(S_IXGRP, stbuf.st_mode)) + continue; + } +#endif + if (!bitset(S_IXOTH, stbuf.st_mode)) + { + ret = EACCES; + break; + } + } while (p != NULL); + if (ret != 0 && tTd(44, 4)) + printf("\t[dir %s] %s\n", fn, errstring(ret)); + if (p != NULL) + *p = '/'; + return ret; +} +/* +** SAFEOPEN -- do a file open with extra checking +** +** Parameters: +** fn -- the file name to open. +** omode -- the open-style mode flags. +** cmode -- the create-style mode flags. +** sff -- safefile flags. +** +** Returns: +** Same as open. +*/ + +#ifndef O_ACCMODE +# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) +#endif + +int +safeopen(fn, omode, cmode, sff) + char *fn; + int omode; + int cmode; + int sff; +{ + int rval; + int fd; + int smode; + struct stat stb; + + if (bitset(O_CREAT, omode)) + sff |= SFF_CREAT; + omode &= ~O_CREAT; + smode = 0; + switch (omode & O_ACCMODE) + { + case O_RDONLY: + smode = S_IREAD; + break; + + case O_WRONLY: + smode = S_IWRITE; + break; + + case O_RDWR: + smode = S_IREAD|S_IWRITE; + break; + + default: + smode = 0; + break; + } + if (bitset(SFF_OPENASROOT, sff)) + rval = safefile(fn, RunAsUid, RunAsGid, RunAsUserName, + sff, smode, &stb); + else + rval = safefile(fn, RealUid, RealGid, RealUserName, + sff, smode, &stb); + if (rval != 0) + { + errno = rval; + return -1; + } + if (stb.st_mode == ST_MODE_NOFILE && bitset(SFF_CREAT, sff)) + omode |= O_EXCL|O_CREAT; + + fd = dfopen(fn, omode, cmode, sff); + if (fd < 0) + return fd; + if (filechanged(fn, fd, &stb, sff)) + { + syserr("554 cannot open: file %s changed after open", fn); + close(fd); + errno = E_SM_FILECHANGE; + return -1; + } + return fd; +} +/* +** SAFEFOPEN -- do a file open with extra checking +** +** Parameters: +** fn -- the file name to open. +** omode -- the open-style mode flags. +** cmode -- the create-style mode flags. +** sff -- safefile flags. +** +** Returns: +** Same as fopen. +*/ + +FILE * +safefopen(fn, omode, cmode, sff) + char *fn; + int omode; + int cmode; + int sff; +{ + int fd; + FILE *fp; + char *fmode; + + switch (omode & O_ACCMODE) + { + case O_RDONLY: + fmode = "r"; + break; + + case O_WRONLY: + if (bitset(O_APPEND, omode)) + fmode = "a"; + else + fmode = "w"; + break; + + case O_RDWR: + if (bitset(O_TRUNC, omode)) + fmode = "w+"; + else if (bitset(O_APPEND, omode)) + fmode = "a+"; + else + fmode = "r+"; + break; + + default: + syserr("safefopen: unknown omode %o", omode); + fmode = "x"; + } + fd = safeopen(fn, omode, cmode, sff); + if (fd < 0) + { + if (tTd(44, 10)) + printf("safefopen: safeopen failed: %s\n", + errstring(errno)); + return NULL; + } + fp = fdopen(fd, fmode); + if (fp != NULL) + return fp; + + if (tTd(44, 10)) + { + printf("safefopen: fdopen(%s, %s) failed: omode=%x, sff=%x, err=%s\n", + fn, fmode, omode, sff, errstring(errno)); +#ifndef NOT_SENDMAIL + dumpfd(fd, TRUE, FALSE); +#endif + } + (void) close(fd); + return NULL; +} +/* +** FILECHANGED -- check to see if file changed after being opened +** +** Parameters: +** fn -- pathname of file to check. +** fd -- file descriptor to check. +** stb -- stat structure from before open. +** sff -- safe file flags. +** +** Returns: +** TRUE -- if a problem was detected. +** FALSE -- if this file is still the same. +*/ + +bool +filechanged(fn, fd, stb, sff) + char *fn; + int fd; + struct stat *stb; + int sff; +{ + struct stat sta; + + if (stb->st_mode == ST_MODE_NOFILE) + { +#if HASLSTAT && BOGUS_O_EXCL + /* only necessary if exclusive open follows symbolic links */ + if (lstat(fn, stb) < 0 || stb->st_nlink != 1) + return TRUE; +#else + return FALSE; +#endif + } + if (fstat(fd, &sta) < 0) + return TRUE; + + if (sta.st_nlink != stb->st_nlink || + sta.st_dev != stb->st_dev || + sta.st_ino != stb->st_ino || +#if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ + sta.st_gen != stb->st_gen || +#endif + sta.st_uid != stb->st_uid || + sta.st_gid != stb->st_gid) + { + if (tTd(44, 8)) + { + printf("File changed after opening:\n"); + printf(" nlink = %ld/%ld\n", + (long) stb->st_nlink, (long) sta.st_nlink); + printf(" dev = %ld/%ld\n", + (long) stb->st_dev, (long) sta.st_dev); + printf(" ino = %ld/%ld\n", + (long) stb->st_ino, (long) sta.st_ino); +#if HAS_ST_GEN + printf(" gen = %ld/%ld\n", + (long) stb->st_gen, (long) sta.st_gen); +#endif + printf(" uid = %ld/%ld\n", + (long) stb->st_uid, (long) sta.st_uid); + printf(" gid = %ld/%ld\n", + (long) stb->st_gid, (long) sta.st_gid); + } + return TRUE; + } + + return FALSE; +} +/* +** DFOPEN -- determined file open +** +** This routine has the semantics of open, except that it will +** keep trying a few times to make this happen. The idea is that +** on very loaded systems, we may run out of resources (inodes, +** whatever), so this tries to get around it. +*/ + +int +dfopen(filename, omode, cmode, sff) + char *filename; + int omode; + int cmode; + int sff; +{ + register int tries; + int fd; + struct stat st; + + for (tries = 0; tries < 10; tries++) + { + sleep((unsigned) (10 * tries)); + errno = 0; + fd = open(filename, omode, cmode); + if (fd >= 0) + break; + switch (errno) + { + case ENFILE: /* system file table full */ + case EINTR: /* interrupted syscall */ +#ifdef ETXTBSY + case ETXTBSY: /* Apollo: net file locked */ +#endif + continue; + } + break; + } + if (!bitset(SFF_NOLOCK, sff) && + fd >= 0 && + fstat(fd, &st) >= 0 && + S_ISREG(st.st_mode)) + { + int locktype; + + /* lock the file to avoid accidental conflicts */ + if ((omode & O_ACCMODE) != O_RDONLY) + locktype = LOCK_EX; + else + locktype = LOCK_SH; + (void) lockfile(fd, filename, NULL, locktype); + errno = 0; + } + return fd; +} diff --git a/usr.sbin/sendmail/test/t_exclopen.c b/usr.sbin/sendmail/test/t_exclopen.c new file mode 100644 index 000000000000..54f7873f4b33 --- /dev/null +++ b/usr.sbin/sendmail/test/t_exclopen.c @@ -0,0 +1,91 @@ +/* +** This program tests your system to see if you have the lovely +** security-defeating semantics that an open with O_CREAT|O_EXCL +** set will successfully open a file named by a symbolic link that +** points to a non-existent file. Sadly, Posix is mute on what +** should happen in this situation. +** +** Results to date: +** AIX 3.2 OK +** BSD family OK +** BSD/OS 2.1 OK +** FreeBSD 2.1 OK +** DEC OSF/1 3.0 OK +** HP-UX 9.04 FAIL +** HP-UX 9.05 FAIL +** HP-UX 9.07 OK +** HP-UX 10.01 OK +** HP-UX 10.10 OK +** HP-UX 10.20 OK +** Irix 5.3 OK +** Irix 6.2 OK +** Linux OK +** NeXT 2.1 OK +** Solaris 2.x OK +** SunOS 4.x OK +** Ultrix 4.3 OK +*/ + +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +char Attacker[128]; +char Attackee[128]; + +main(argc, argv) + int argc; + char **argv; +{ + struct stat st; + + sprintf(Attacker, "/tmp/attacker.%d.%ld", getpid(), time(NULL)); + sprintf(Attackee, "/tmp/attackee.%d.%ld", getpid(), time(NULL)); + + if (symlink(Attackee, Attacker) < 0) + { + printf("Could not create %s->%s symlink: %d\n", + Attacker, Attackee, errno); + bail(1); + } + (void) unlink(Attackee); + if (stat(Attackee, &st) >= 0) + { + printf("%s already exists -- remove and try again.\n", + Attackee); + bail(1); + } + if (open(Attacker, O_WRONLY|O_CREAT|O_EXCL, 0644) < 0) + { + int saveerr = errno; + + if (stat(Attackee, &st) >= 0) + { + printf("Weird. Open failed but %s was created anyhow (errno = %d)\n", + Attackee, saveerr); + bail(1); + } + printf("Good show! Exclusive open works properly with symbolic links (errno = %d).\n", + saveerr); + bail(0); + } + if (stat(Attackee, &st) < 0) + { + printf("Weird. Open succeeded but %s was not created\n", + Attackee); + bail(2); + } + printf("Bad news: you can do an exclusive open through a symbolic link\n"); + printf("\tBe sure you #define BOGUS_O_EXCL in conf.h\n"); + bail(1); +} + +bail(stat) + int stat; +{ + (void) unlink(Attacker); + (void) unlink(Attackee); + exit(stat); +} diff --git a/usr.sbin/wlconfig/wlconfig.8 b/usr.sbin/wlconfig/wlconfig.8 new file mode 100644 index 000000000000..a16db4e94103 --- /dev/null +++ b/usr.sbin/wlconfig/wlconfig.8 @@ -0,0 +1,131 @@ +.Dd December 26 1996 +.Os +.Dt WLCONFIG 8 +.Sh NAME +.Nm wlconfig +.Nd read/write wavelan config parameters +.Sh SYNOPSIS +.Nm wlconfig +.Ar ifname +.Op Ar param value ... +.Sh DESCRIPTION +The +.Nm wlconfig +command can be used to read and set parameters for the NCR/AT&T Wavelan +radio LAN card. Various parameters stored in the nonvolatile Parameter +Storage Area (PSA) on the card can be modified with this program, which +obviates the need for the DOS-based +.Nm instconf.exe +program. It can also be used to interrogate the optional signal +strength cache which may have been compiled into the driver. +.Pp +The +.Ar ifname +parameter specifies the wavelan interface name (eg. +.Pa wl0 +). If no other arguments are supplied, the current contents of the PSA +are interpreted and displayed. +.Pp +The +.Ar param +and +.Ar value +arguments can be used to change the value of several parameters. +Any number of +.Ar param value +pairs may be supplied. +.Bl -tag -width 15n -compat -offset indent +.It Va param +.Va value +.It irq +IRQ value (used at next reset), may be one of 3,4,5,6,10,11,12,15 +.It mac +Local MAC value (ethernet address) +.It macsel +.Sq soft +(as set by the +.Sq mac +parameter) or +.Sq default +(as set at the factory). +.It nwid +The NWID is a 2-byte parameter passed to the card's radio modem. +NWIDs allow multiple logically discrete networks to operate +independantly whilse occupying the same airspace. +Packets with a different NWID are simply ignored by the modem. +In the hardware, NWIDs are stored long-term in non-volative memory +(called the PSA or programmable storage area), and are loaded by +software into the radio modem when the driver is +initialized. This sets the default NWID loaded at startup. +.It curnwid +This sets the current operating NWID (but does not save it to the +PSA). +.It cache +The driver may maintain a per interface fixed size cache of signal strength, +silence, and quality levels, which are indexed by sender MAC addresses. +Input packets are stored in the cache, and when received, the values +stored in the radio modem are interrogated and stored. +There are also two sysctl values (iponly and multicast only) which +can be used for filtering out some input packets. By default, the +cache mechanism stores only non-unicast IP packets, but this can +be changed with sysctl(8). Each non-filtered +input packet causes a cache update, hence one can monitor +the antennae signal strength to a remote system. +There are three commands that can be given as values: +.Sq raw , +which prints out the raw signal strength data as found in the radio +modem hardware value, +.Sq scale , +which scales the raw hardware values to 0..100%, and +.Sq zero +which clears out the cache in case you want to store new samples. +.El +.Pp +Note that if the IRQ on the Wavelan card is incorrect, the interface +will be configured, but will not function. The +.Nm wlconfig +program should then be used to reconfigure the card to a sensible +value. +.Sh EXAMPLES +Set the NWID to 0x1234 : +.Bd -literal -offset +# wlconfig wl0 nwid 0x1234 +.Ed +.Pp +Show the current settings : +.Bd -literal -offset +# wlconfig wl0 +Board type : ISA +Base address options : 0x300, 0x390, 0x3c0, 0x3e0 +Waitstates : 0 +Bus mode : ISA +IRQ : 10 +Default MAC address : 08:00:0e:20:3d:4b +Soft MAC address : 00:00:00:00:00:00 +Current MAC address : Default +Adapter compatability : PC-AT 2.4GHz +Threshold preset : 1 +Call code required : NO +Subband : 2425MHz +Quality threshold : 3 +Hardware version : 0 (Rel1/Rel2) +Network ID enable : YES +NWID : 0xdead +Datalink security : NO +Databus width : 16 (variable) +Configuration state : unconfigured +CRC-16 : 0x3c26 +CRC status : OK +.Pp +Print a scaled version of the signal strength cache : +.Bd -literal -offset +# wlconfig wl0 cache scale +.Ed +.Sh SEE ALSO +.Xr wl 4, +.Xr sysctl 8 . +.Sh HISTORY +This implementation of the +.Nm wlconfig +command is completely new, written for Hilink Internet by Michael Smith, +and updated by Jim Binkley &c. diff --git a/usr.sbin/wlconfig/wlconfig.c b/usr.sbin/wlconfig/wlconfig.c new file mode 100644 index 000000000000..51153f9291f9 --- /dev/null +++ b/usr.sbin/wlconfig/wlconfig.c @@ -0,0 +1,432 @@ +/* + * Copyright (C) 1996 + * Michael Smith. 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. + * + * THIS SOFTWARE IS PROVIDED BY Michael Smith 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 Michael Smith 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. + * + * $Id: wlconfig.c,v 1.3 1997/08/01 03:50:23 msmith Exp $ + * + */ +/* + * wlconfig.c + * + * utility to read out and change various WAVELAN parameters. + * Currently supports NWID and IRQ values. + * + * The NWID is used by 2 or more wavelan controllers to determine + * if packets should be received or not. It is a filter that + * is roughly analogous to the "channel" setting with a garage + * door controller. Two companies side by side with wavelan devices + * that could actually hear each other can use different NWIDs + * and ignore packets. In truth however, the air space is shared, + * and the NWID is a virtual filter. + * + * In the current set of wavelan drivers, ioctls changed only + * the runtime radio modem registers which act in a manner analogous + * to an ethernet transceiver. The ioctls do not change the + * stored nvram PSA (or parameter storage area). At boot, the PSA + * values are stored in the radio modem. Thus when the + * system reboots it will restore the wavelan NWID to the value + * stored in the PSA. The NCR/ATT dos utilities must be used to + * change the initial NWID values in the PSA. The wlconfig utility + * may be used to set a different NWID at runtime; this is only + * permitted while the interface is up and running. + * + * By contrast, the IRQ value can only be changed while the + * Wavelan card is down and unconfigured, and it will remain + * disabled after an IRQ change until reboot. + * + */ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <machine/if_wl_wavelan.h> + +#include <net/if.h> +#if __FreeBSD__ >= 3 +#include <net/if_var.h> +#endif +#include <netinet/in.h> +#include <netinet/if_ether.h> +extern struct ether_addr *ether_aton(char *a); + +#include <err.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> + +/* translate IRQ bit to number */ +/* array for maping irq numbers to values for the irq parameter register */ +static int irqvals[16] = { + 0, 0, 0, 0x01, 0x02, 0x04, 0, 0x08, 0, 0, 0x10, 0x20, 0x40, 0, 0, 0x80 +}; + +/* cache */ +static int w_sigitems; /* count of valid items */ +static struct w_sigcache wsc[MAXCACHEITEMS]; + +int +wlirq(int irqval) +{ + int irq; + + for(irq = 0; irq < 16; irq++) + if(irqvals[irq] == irqval) + return(irq); + return 0; +} + +char *compat_type[] = { + "PC-AT 915MHz", + "PC-MC 915MHz", + "PC-AT 2.4GHz", + "PC-MC 2.4GHz", + "PCCARD or 1/2 size AT, 915MHz or 2.4GHz" +}; + +char *subband[] = { + "915MHz/see WaveModem", + "2425MHz", + "2460MHz", + "2484MHz", + "2430.5MHz" +}; + + +/* +** print_psa +** +** Given a pointer to a PSA structure, print it out +*/ +void +print_psa(u_char *psa, int currnwid) +{ + int nwid; + + /* + ** Work out what sort of board we have + */ + if (psa[0] == 0x14) { + printf("Board type : Microchannel\n"); + } else { + if (psa[1] == 0) { + printf("Board type : PCCARD\n"); + } else { + printf("Board type : ISA"); + if ((psa[4] == 0) && + (psa[5] == 0) && + (psa[6] == 0)) + printf(" (DEC OEM)"); + printf("\n"); + printf("Base address options : 0x300, 0x%02x0, 0x%02x0, 0x%02x0\n", + (int)psa[1], (int)psa[2], (int)psa[3]); + printf("Waitstates : %d\n",psa[7] & 0xf); + printf("Bus mode : %s\n",(psa[7] & 0x10) ? "EISA" : "ISA"); + printf("IRQ : %d\n",wlirq(psa[8])); + } + } + printf("Default MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n", + psa[0x10],psa[0x11],psa[0x12],psa[0x13],psa[0x14],psa[0x15]); + printf("Soft MAC address : %02x:%02x:%02x:%02x:%02x:%02x\n", + psa[0x16],psa[0x17],psa[0x18],psa[0x19],psa[0x1a],psa[0x1b]); + printf("Current MAC address : %s\n",(psa[0x1c] & 0x1) ? "Soft" : "Default"); + printf("Adapter compatability : "); + if (psa[0x1d] < 5) { + printf("%s\n",compat_type[psa[0x1d]]); + } else { + printf("unknown\n"); + } + printf("Threshold preset : %d\n",psa[0x1e]); + printf("Call code required : %s\n",(psa[0x1f] & 0x1) ? "YES" : "NO"); + if (psa[0x1f] & 0x1) + printf("Call code : 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + psa[0x30],psa[0x31],psa[0x32],psa[0x33],psa[0x34],psa[0x35],psa[0x36],psa[0x37]); + printf("Subband : %s\n",subband[psa[0x20] & 0xf]); + printf("Quality threshold : %d\n",psa[0x21]); + printf("Hardware version : %d (%s)\n",psa[0x22],psa[0x22] ? "Rel3" : "Rel1/Rel2"); + printf("Network ID enable : %s\n",(psa[0x25] & 0x1) ? "YES" : "NO"); + if (psa[0x25] & 0x1) { + nwid = (psa[0x23] << 8) + psa[0x24]; + printf("NWID : 0x%04x\n",nwid); + if (nwid != currnwid) { + printf("Current NWID : 0x%04x\n",currnwid); + } + } + printf("Datalink security : %s\n",(psa[0x26] & 0x1) ? "YES" : "NO"); + if (psa[0x26] & 0x1) { + printf("Encryption key : "); + if (psa[0x27] == 0) { + printf("DENIED\n"); + } else { + printf("0x%02x%02x%02x%02x%02x%02x%02x%02x\n", + psa[0x27],psa[0x28],psa[0x29],psa[0x2a],psa[0x2b],psa[0x2c],psa[0x2d],psa[0x2e]); + } + } + printf("Databus width : %d (%s)\n", + (psa[0x2f] & 0x1) ? 16 : 8, (psa[0x2f] & 0x80) ? "fixed" : "variable"); + printf("Configuration state : %sconfigured\n",(psa[0x38] & 0x1) ? "" : "un"); + printf("CRC-16 : 0x%02x%02x\n",psa[0x3e],psa[0x3d]); + printf("CRC status : "); + switch(psa[0x3f]) { + case 0xaa: + printf("OK\n"); + break; + case 0x55: + printf("BAD\n"); + break; + default: + printf("Error\n"); + break; + } +} + + +void +syntax(char *pname) +{ + fprintf(stderr,"Usage: %s <ifname> [<param> <value> ...]\n",pname); + fprintf(stderr," <ifname> Wavelan interface name.\n"); + fprintf(stderr," <param> Parameter name (see below)\n"); + fprintf(stderr," <value> New value for parameter.\n"); + fprintf(stderr," Parameter name: Value:\n"); + fprintf(stderr," irq 3,4,5,6,10,11,12,15\n"); + fprintf(stderr," mac soft ethernet address\n"); + fprintf(stderr," macsel soft or default\n"); + fprintf(stderr," nwid default NWID (0x0-0xffff)\n"); + fprintf(stderr," currnwid current NWID (0x0-0xffff) or 'get'\n"); + fprintf(stderr," cache signal strength cache\n"); + fprintf(stderr," cache values = { raw, scale, zero }\n"); + exit(1); +} + + +void +get_cache(int sd, struct ifreq *ifr) +{ + /* get the cache count */ + if (ioctl(sd, SIOCGWLCITEM, (caddr_t)ifr)) { + perror("SIOCGWLCITEM - get cache count"); + exit(1); + } + w_sigitems = (int) ifr->ifr_data; + + ifr->ifr_data = (caddr_t) &wsc; + /* get the cache */ + if (ioctl(sd, SIOCGWLCACHE, (caddr_t)ifr)) { + perror("SIOCGWLCACHE - get cache count"); + exit(1); + } +} + +static int +scale_value(int value, int max) +{ + double dmax = (double) max; + if (value > max) + return(100); + return((value/dmax) * 100); +} + +static void +dump_cache(int rawFlag) +{ + int i; + int signal, silence, quality; + + if (rawFlag) + printf("signal range 0..63: silence 0..63: quality 0..15\n"); + else + printf("signal range 0..100: silence 0..100: quality 0..100\n"); + + /* after you read it, loop through structure,i.e. wsc + * print each item: + */ + for(i = 0; i < w_sigitems; i++) { + printf("[%d:%d]>\n", i+1, w_sigitems); + printf("\tip: %d.%d.%d.%d,",((wsc[i].ipsrc >> 0) & 0xff), + ((wsc[i].ipsrc >> 8) & 0xff), + ((wsc[i].ipsrc >> 16) & 0xff), + ((wsc[i].ipsrc >> 24) & 0xff)); + printf(" mac: %02x:%02x:%02x:%02x:%02x:%02x\n", + wsc[i].macsrc[0]&0xff, + wsc[i].macsrc[1]&0xff, + wsc[i].macsrc[2]&0xff, + wsc[i].macsrc[3]&0xff, + wsc[i].macsrc[4]&0xff, + wsc[i].macsrc[5]&0xff); + if (rawFlag) { + signal = wsc[i].signal; + silence = wsc[i].silence; + quality = wsc[i].quality; + } + else { + signal = scale_value(wsc[i].signal, 63); + silence = scale_value(wsc[i].silence, 63); + quality = scale_value(wsc[i].quality, 15); + } + printf("\tsignal: %d, silence: %d, quality: %d, ", + signal, + silence, + quality); + printf("snr: %d\n", signal - silence); + } +} + +#define raw_cache() dump_cache(1) +#define scale_cache() dump_cache(0) + +void +main(int argc, char *argv[]) +{ + int sd; + struct ifreq ifr; + u_char psabuf[0x40]; + int val, argind, i; + char *cp, *param, *value; + struct ether_addr *ea; + int work = 0; + int currnwid; + + if ((argc < 2) || (argc % 2)) + syntax(argv[0]); + + /* get a socket */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0) + err(1,"socket"); + strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)); + ifr.ifr_addr.sa_family = AF_INET; + + /* get the PSA */ + ifr.ifr_data = (caddr_t)psabuf; + if (ioctl(sd, SIOCGWLPSA, (caddr_t)&ifr)) + err(1,"Get PSA"); + + /* get the current NWID */ + if (ioctl(sd, SIOCGWLCNWID, (caddr_t)&ifr)) + err(1,"Get NWID"); + currnwid = (int)ifr.ifr_data; + + /* just dump and exit? */ + if (argc == 2) { + print_psa(psabuf, currnwid); + exit(0); + } + + /* loop reading arg pairs */ + for (argind = 2; argind < argc; argind += 2) { + + param = argv[argind]; + value = argv[argind+1]; + + /* What to do? */ + + if (!strcasecmp(param,"currnwid")) { /* set current NWID */ + val = strtol(value,&cp,0); + if ((val < 0) || (val > 0xffff) || (cp == value)) + errx(1,"Bad NWID '%s'",value); + + ifr.ifr_data = (caddr_t)val; + if (ioctl(sd, SIOCSWLCNWID, (caddr_t)&ifr)) + err(1,"Set NWID (interface not up?)"); + continue ; + } + + if (!strcasecmp(param,"irq")) { + val = strtol(value,&cp,0); + val = irqvals[val]; + if ((val == 0) || (cp == value)) + errx(1,"Bad IRQ '%s'",value); + psabuf[WLPSA_IRQNO] = (u_char)val; + work = 1; + continue; + } + + if (!strcasecmp(param,"mac")) { + if ((ea = ether_aton(value)) == NULL) + errx(1,"Bad ethernet address '%s'",value); + for (i = 0; i < 6; i++) + psabuf[WLPSA_LOCALMAC + i] = ea->octet[i]; + work = 1; + continue; + } + + if (!strcasecmp(param,"macsel")) { + if (!strcasecmp(value,"local")) { + psabuf[WLPSA_MACSEL] |= 0x1; + work = 1; + continue; + } + if (!strcasecmp(value,"universal")) { + psabuf[WLPSA_MACSEL] &= ~0x1; + work = 1; + continue; + } + errx(1,"Bad macsel value '%s'",value); + } + + if (!strcasecmp(param,"nwid")) { + val = strtol(value,&cp,0); + if ((val < 0) || (val > 0xffff) || (cp == value)) + errx(1,"Bad NWID '%s'",value); + psabuf[WLPSA_NWID] = (val >> 8) & 0xff; + psabuf[WLPSA_NWID+1] = val & 0xff; + work = 1; + continue; + } + if (!strcasecmp(param,"cache")) { + + /* raw cache dump + */ + if (!strcasecmp(value,"raw")) { + get_cache(sd, &ifr); + raw_cache(); + continue; + } + /* scaled cache dump + */ + else if (!strcasecmp(value,"scale")) { + get_cache(sd, &ifr); + scale_cache(); + continue; + } + /* zero out cache + */ + else if (!strcasecmp(value,"zero")) { + if (ioctl(sd, SIOCDWLCACHE, (caddr_t)&ifr)) + err(1,"Zero cache"); + continue; + } + errx(1,"Unknown value '%s'", value); + } + errx(1,"Unknown parameter '%s'",param); + } + if (work) { + ifr.ifr_data = (caddr_t)psabuf; + if (ioctl(sd, SIOCSWLPSA, (caddr_t)&ifr)) + err(1,"Set PSA"); + } +} |
