Index: stable/6/contrib/sendmail/cf/feature/badmx.m4 =================================================================== --- stable/6/contrib/sendmail/cf/feature/badmx.m4 (nonexistent) +++ stable/6/contrib/sendmail/cf/feature/badmx.m4 (revision 168599) @@ -0,0 +1,22 @@ +divert(-1) +# +# Copyright (c) 2006 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0) +VERSIONID(`$Id: badmx.m4,v 1.1 2006/12/16 00:56:32 ca Exp $') +divert(-1) + +define(`_BADMX_CHK_', 1) + +LOCAL_CONFIG +Kmxlist bestmx -z: -T +Kbadmx regex -a ^(([0-9]{1,3}\.){3}[0-9]){0,1}\.$ +KdnsA dns -R A -a. -T +KBadMXIP regex -a ifelse(defn(`_ARG_'), `', `^(127\.|10\.|0\.0\.0\.0)', `_ARG_') Property changes on: stable/6/contrib/sendmail/cf/feature/badmx.m4 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/cf/feature/block_bad_helo.m4 =================================================================== --- stable/6/contrib/sendmail/cf/feature/block_bad_helo.m4 (nonexistent) +++ stable/6/contrib/sendmail/cf/feature/block_bad_helo.m4 (revision 168599) @@ -0,0 +1,18 @@ +divert(-1) +# +# Copyright (c) 2006 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0)dnl +VERSIONID(`$Id: block_bad_helo.m4,v 1.1 2006/06/15 22:49:30 ca Exp $') +divert(-1) + +define(`_BLOCK_BAD_HELO_', `')dnl +RELAY_DOMAIN(`127.0.0.1')dnl +LOCAL_DOMAIN(`[127.0.0.1]')dnl Property changes on: stable/6/contrib/sendmail/cf/feature/block_bad_helo.m4 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/cf/feature/require_rdns.m4 =================================================================== --- stable/6/contrib/sendmail/cf/feature/require_rdns.m4 (nonexistent) +++ stable/6/contrib/sendmail/cf/feature/require_rdns.m4 (revision 168599) @@ -0,0 +1,16 @@ +divert(-1) +# +# Copyright (c) 2006 Sendmail, Inc. and its suppliers. +# All rights reserved. +# +# By using this file, you agree to the terms and conditions set +# forth in the LICENSE file which can be found at the top level of +# the sendmail distribution. +# +# + +divert(0)dnl +VERSIONID(`$Id: require_rdns.m4,v 1.1 2006/06/15 22:49:30 ca Exp $') +divert(-1) + +define(`_REQUIRE_RDNS_', `') Property changes on: stable/6/contrib/sendmail/cf/feature/require_rdns.m4 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/include/sm/misc.h =================================================================== --- stable/6/contrib/sendmail/include/sm/misc.h (nonexistent) +++ stable/6/contrib/sendmail/include/sm/misc.h (revision 168599) @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Id: misc.h,v 1.1 2006/06/28 23:57:59 ca Exp $ + */ + +#ifndef SM_MISC_H +# define SM_MISC_H 1 + +int sm_memstat_open __P((void)); +int sm_memstat_close __P((void)); +int sm_memstat_get __P((char *, long *)); + +#endif /* ! SM_MISC_H */ Property changes on: stable/6/contrib/sendmail/include/sm/misc.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/include/sm/os/sm_os_qnx.h =================================================================== --- stable/6/contrib/sendmail/include/sm/os/sm_os_qnx.h (nonexistent) +++ stable/6/contrib/sendmail/include/sm/os/sm_os_qnx.h (revision 168599) @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2007 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Id: sm_os_qnx.h,v 1.1 2007/03/21 23:56:20 ca Exp $ + */ + +/* +** sm_os_qnx.h -- platform definitions for QNX +*/ + +#define SM_CONF_SYS_CDEFS_H 1 + +#ifndef SM_CONF_SETITIMER +# define SM_CONF_SETITIMER 0 +#endif /* SM_CONF_SETITIMER */ Property changes on: stable/6/contrib/sendmail/include/sm/os/sm_os_qnx.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/include/sm/sendmail.h =================================================================== --- stable/6/contrib/sendmail/include/sm/sendmail.h (nonexistent) +++ stable/6/contrib/sendmail/include/sm/sendmail.h (revision 168599) @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +/* +** SENDMAIL.H -- MTA-specific definitions for sendmail. +*/ + +#ifndef _SM_SENDMAIL_H +# define _SM_SENDMAIL_H 1 + +/* "out of band" indicator */ +#define METAQUOTE ((unsigned char)0377) /* quotes the next octet */ + +extern int dequote_internal_chars __P((char *, char *, int)); +extern char *quote_internal_chars __P((char *, char *, int *)); +extern char *str2prt __P((char *)); + +#endif /* ! _SM_SENDMAIL_H */ Property changes on: stable/6/contrib/sendmail/include/sm/sendmail.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/include/sm/tailq.h =================================================================== --- stable/6/contrib/sendmail/include/sm/tailq.h (nonexistent) +++ stable/6/contrib/sendmail/include/sm/tailq.h (revision 168599) @@ -0,0 +1,153 @@ +/* $OpenBSD: queue.h,v 1.30 2005/10/25 06:37:47 otto Exp $ */ +/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef SM_TAILQ_H_ +#define SM_TAILQ_H_ + +/* + * This file is a modified copy of queue.h from a BSD system: + * we only need tail queues here. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + */ + +/* + * Tail queue definitions. + */ +#define SM_TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ +} + +#define SM_TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define SM_TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} + +/* + * tail queue access methods + */ +#define SM_TAILQ_FIRST(head) ((head)->tqh_first) +#define SM_TAILQ_END(head) NULL +#define SM_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define SM_TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +/* XXX */ +#define SM_TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define SM_TAILQ_EMPTY(head) \ + (SM_TAILQ_FIRST(head) == SM_TAILQ_END(head)) + +#define SM_TAILQ_FOREACH(var, head, field) \ + for((var) = SM_TAILQ_FIRST(head); \ + (var) != SM_TAILQ_END(head); \ + (var) = SM_TAILQ_NEXT(var, field)) + +#define SM_TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for((var) = SM_TAILQ_LAST(head, headname); \ + (var) != SM_TAILQ_END(head); \ + (var) = SM_TAILQ_PREV(var, headname, field)) + +/* + * Tail queue functions. + */ +#define SM_TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (0) + +#define SM_TAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (0) + +#define SM_TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (0) + +#define SM_TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (0) + +#define SM_TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (0) + +#define SM_TAILQ_REMOVE(head, elm, field) do { \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ +} while (0) + +#define SM_TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ +} while (0) + +#endif /* !SM_TAILQ_H_ */ Property changes on: stable/6/contrib/sendmail/include/sm/tailq.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/docs/smfi_addrcpt_par.html =================================================================== --- stable/6/contrib/sendmail/libmilter/docs/smfi_addrcpt_par.html (nonexistent) +++ stable/6/contrib/sendmail/libmilter/docs/smfi_addrcpt_par.html (revision 168599) @@ -0,0 +1,88 @@ + +smfi_addrcpt_par + + +

smfi_addrcpt_par

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_addrcpt_par(
+	SMFICTX *ctx,
+	char *rcpt,
+	char *args
+);
+
+Add a recipient for the current message including ESMTP arguments. +
DESCRIPTION + + + + + + + + + +
Called WhenCalled only from xxfi_eom.
EffectsAdd a recipient to the message envelope.
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
rcptThe new recipient's address. +
argsThe new recipient's ESMTP parameters. +
+
RETURN VALUESsmfi_addrcpt will fail and return MI_FAILURE if: +
  • rcpt is NULL. +
  • Adding recipients in the current connection state is invalid. +
  • A network error occurs. +
  • SMFIF_ADDRCPT_PAR was not set when + smfi_register was called. +
+Otherwise, it will return MI_SUCCESS. +
NOTES +A filter which calls smfi_addrcpt must have set the SMFIF_ADDRCPT_PAR flag +in the smfiDesc_str passed to +smfi_register. +
+ +
+ +Copyright (c) 2006 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + Property changes on: stable/6/contrib/sendmail/libmilter/docs/smfi_addrcpt_par.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/docs/smfi_chgfrom.html =================================================================== --- stable/6/contrib/sendmail/libmilter/docs/smfi_chgfrom.html (nonexistent) +++ stable/6/contrib/sendmail/libmilter/docs/smfi_chgfrom.html (revision 168599) @@ -0,0 +1,94 @@ + +smfi_chgfrom + + +

smfi_chgfrom

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_chgfrom(
+	SMFICTX *ctx,
+	const char *mail,
+	char *args
+);
+
+Change the envelope sender (MAIL From) of the current message. +
DESCRIPTION + + + + + + + + + +
Called WhenCalled only from xxfi_eom.
EffectsChange the envelope sender (MAIL From) of the current message.
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
mailThe new sender address. +
argsESMTP arguments. +
+
RETURN VALUESsmfi_chgfrom will fail and return MI_FAILURE if: +
  • mail is NULL. +
  • Changing the sender in the current connection state is invalid. +
  • A network error occurs. +
  • SMFIF_CHGFROM was not set when smfi_register was called. +
+Otherwise, it will return MI_SUCCESS. +
NOTES +A filter which calls smfi_chgfrom must have set the SMFIF_CHGFROM flag +in the smfiDesc_str passed to +smfi_register. +
+Even though all ESMTP arguments could be set via this call, +it does not make sense to do so for many of them, +e.g., SIZE and BODY. +Setting those may cause problems, proper care must be taken. +Moreover, there is no feedback from the MTA to the milter +whether the call was successful. +
+ +
+ +Copyright (c) 2006 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + Property changes on: stable/6/contrib/sendmail/libmilter/docs/smfi_chgfrom.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/docs/smfi_setsymlist.html =================================================================== --- stable/6/contrib/sendmail/libmilter/docs/smfi_setsymlist.html (nonexistent) +++ stable/6/contrib/sendmail/libmilter/docs/smfi_setsymlist.html (revision 168599) @@ -0,0 +1,107 @@ + +smfi_setsymlist + + +

smfi_setsymlist

+ + + + + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_setsymlist(
+        SMFICTX    *ctx, 
+	int        stage,
+	char       *macros
+);
+
+Set the list of macros that the milter wants to receive from the MTA +for a protocol stage. +
DESCRIPTION + + + + + + + + + +
Called WhenThis function must only be called during +xxfi_negotiate(). +
EffectsThis function can be used to override the list of macros that the +milter wants to receive from the MTA. +
+ + +
ARGUMENTS + + + + + + + + + + + + +
ArgumentDescription
ctxthe opaque context structure. +
stagethe protocol stage during which the macro list should be used. + See the file + include/libmilter/mfapi.h for legal values, + look for the C macros with the prefix + SMFIM_. + Available protocol stages are at least + the initial connection, HELO/EHLO, MAIL, RCPT, DATA, + end of header, and + the end of a message. +
macroslist of macros (separated by space). + Example: "{rcpt_mailer} {rcpt_host}" +
+
RETURN VALUESMI_FAILURE is returned if +
    +
  • there is not enough free memory to make a copy of the macro list, +
  • macros is NULL or empty, +
  • stage is not a valid protocol stage, +
  • the macro list for +stage has been set before. +
+Otherwise MI_SUCCESS is returned. +
NOTESThere is an internal limit on the number of macros that can be +set (currently 5), +however, this limit is not enforced by libmilter, only by the MTA, +but a possible violation of this restriction is not communicated back to +the milter.
+ +
+ +Copyright (c) 2006 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + Property changes on: stable/6/contrib/sendmail/libmilter/docs/smfi_setsymlist.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/docs/smfi_version.html =================================================================== --- stable/6/contrib/sendmail/libmilter/docs/smfi_version.html (nonexistent) +++ stable/6/contrib/sendmail/libmilter/docs/smfi_version.html (revision 168599) @@ -0,0 +1,86 @@ + +smfi_version() + + +

smfi_version()

+ + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+int smfi_version(
+	unsigned int *pmajor,
+	unsigned int *pminor,
+	unsigned int *ppl
+);
+
+Get the (runtime) version of libmilter. +
DESCRIPTION + + + + + + + + + +
Called Whensmfi_version may be called at any time.
EffectsNone.
+ + +
ARGUMENTS + + + + + + + + +
ArgumentDescription
pmajorPointer to an unsigned int variable to store major version number. +
pminorPointer to an unsigned int variable to store minor version number. +
pplPointer to an unsigned int variable to store patch level number. +
+
RETURN VALUESsmfi_version returns MI_SUCCESS.
+ +Note: the compile time version of libmilter is available in the macro +SMFI_VERSION. +A milter can check this macro to determine which functions to use +(at compile time via C preprocessor statements). +Using this macro and the +smfi_version() +function, +a milter can determine at runtime whether it has been (dynamically) +linked against the expected libmilter version. +To extract the major and minor version as well as the current patch level +from this macro, the macros +SM_LM_VRS_MAJOR(v), +SM_LM_VRS_MINOR(v), and +SM_LM_VRS_PLVL(v) +can be used, respectively. + + +
+ +Copyright (c) 2006, 2007 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + Property changes on: stable/6/contrib/sendmail/libmilter/docs/smfi_version.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/docs/xxfi_data.html =================================================================== --- stable/6/contrib/sendmail/libmilter/docs/xxfi_data.html (nonexistent) +++ stable/6/contrib/sendmail/libmilter/docs/xxfi_data.html (revision 168599) @@ -0,0 +1,89 @@ + +xxfi_data + + +

xxfi_data

+ + + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_data)(
+	SMFICTX *ctx
+);
+
+Handle the DATA command. +
DESCRIPTION + + + + + + + + +
Called Whenxxfi_data is called when the client uses the DATA command. +
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + +
ArgumentDescription
ctxOpaque context structure. +
+
SPECIAL RETURN VALUES + + + + + + + + + + + + + + + + + +
Return valueDescription
SMFIS_TEMPFAILReject this message with a temporary error. +
SMFIS_REJECTReject this message. +
SMFIS_DISCARDAccept and silently discard this message. +
SMFIS_ACCEPTAccept this message. +
+
NOTESFor more details on ESMTP responses, please see RFC +1869.
+ +
+ +Copyright (c) 2006 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + Property changes on: stable/6/contrib/sendmail/libmilter/docs/xxfi_data.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/docs/xxfi_negotiate.html =================================================================== --- stable/6/contrib/sendmail/libmilter/docs/xxfi_negotiate.html (nonexistent) +++ stable/6/contrib/sendmail/libmilter/docs/xxfi_negotiate.html (revision 168599) @@ -0,0 +1,277 @@ + +xxfi_negotiate + + +

xxfi_negotiate

+ + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+#include <libmilter/mfdef.h>
+sfsistat (*xxfi_negotiate)(
+        SMFICTX    *ctx, 
+	unsigned long f0,
+	unsigned long f1,
+	unsigned long f2,
+	unsigned long f3,
+	unsigned long *pf0,
+	unsigned long *pf1,
+	unsigned long *pf2,
+	unsigned long *pf3);
+
+
DESCRIPTION + + + + + + + + + +
Called WhenOnce, at the start of each SMTP connection.
Default BehaviorReturn SMFIS_ALL_OPTS to change nothing.
+ +
ARGUMENTS + + + + + + + + + + + + + + + + + + +
ArgumentDescription
ctxthe opaque context structure. +
f0the actions offered by the MTA. +
f1the protocol steps offered by the MTA. +
f2for future extensions. +
f3for future extensions. +
pf0the actions requested by the milter. +
pf1the protocol steps requested by the milter. +
pf2for future extensions. +
pf3for future extensions. +
+
SPECIAL RETURN VALUES + + + + + + + + + + + + + +
Return valueDescription
SMFIS_ALL_OPTS +If a milter just wants to inspect the available protocol steps +and actions, then it can return +SMFIS_ALL_OPTS +and the MTA will make all protocol steps and actions available +to the milter. +In this case, no values should be assigned to the output parameters +pf0 - pf3 +as they will be ignored. +
SMFIS_REJECTMilter startup fails and it will not be contacted again +(for the current connection). +
SMFIS_CONTINUEContinue processing. + In this case the milter must set all output parameters + pf0 - pf3. + See below for an explanation how to set those output parameters. +
+
NOTESThis function allows a milter to dynamically determine and +request operations and actions during startup. +In previous versions, the actions (f0) were fixed in the +flags field of the +smfiDesc +structure +and the protocol steps (f1) were implicitly derived by checking whether +a callback was defined. +Due to the extensions in the new milter version, +such a static selection will not work if a milter requires +new actions that are not available when talking to an older MTA. +Hence in the negotiation callback a milter can determine +which operations are available and dynamically select +those which it needs and which are offered. +If some operations are not available, the milter may either fall back +to an older mode or abort the session and ask the user to upgrade. + + + +

+Protocol steps +(f1, *pf1): +

+ +

+The available actions +(f0, *pf0) +are + +described +elsewhere (xxfi_flags). + +

+If a milter returns SMFIS_CONTINUE, then it must +set the desired actions and protocol steps +via the (output) parameters +pf0 +and +pf1 +(which correspond to +f0 +and +f1, respectively). +The (output) parameters +pf2 and +pf3 +should be set to 0 for compatibility with future versions. + +

+ +
+ +Copyright (c) 2006 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + Property changes on: stable/6/contrib/sendmail/libmilter/docs/xxfi_negotiate.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/docs/xxfi_unknown.html =================================================================== --- stable/6/contrib/sendmail/libmilter/docs/xxfi_unknown.html (nonexistent) +++ stable/6/contrib/sendmail/libmilter/docs/xxfi_unknown.html (revision 168599) @@ -0,0 +1,84 @@ + +xxfi_unknown + + +

xxfi_unknown

+ + + + + + + + + + + + + + + + + +
SYNOPSIS +
+#include <libmilter/mfapi.h>
+sfsistat (*xxfi_unknown)(
+	SMFICTX *ctx,
+	const char *arg
+);
+
+Handle unknown and unimplemented SMTP commands. +
DESCRIPTION + + + + + + + + +
Called Whenxxfi_unknown is called when the client uses an SMTP command +that is either unknown or not implemented by the MTA. +
Default BehaviorDo nothing; return SMFIS_CONTINUE.
+ + +
ARGUMENTS + + + + + + +
ArgumentDescription
ctxOpaque context structure. +
argSMTP command including all arguments. +
+
SPECIAL RETURN VALUES + + + + + + + + + +
Return valueDescription
SMFIS_TEMPFAILReject this message with a temporary error. +
SMFIS_REJECTReject this message. +
+
NOTESThe SMTP command will always be rejected by the server, +it is only possible to return a different error code. +
+ +
+ +Copyright (c) 2006 Sendmail, Inc. and its suppliers. +All rights reserved. +
+By using this file, you agree to the terms and conditions set +forth in the LICENSE. +
+ + Property changes on: stable/6/contrib/sendmail/libmilter/docs/xxfi_unknown.html ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/example.c =================================================================== --- stable/6/contrib/sendmail/libmilter/example.c (nonexistent) +++ stable/6/contrib/sendmail/libmilter/example.c (revision 168599) @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Id: example.c,v 8.3 2006/12/20 21:22:34 ca Exp $ + */ + +/* +** A trivial example filter that logs all email to a file. +** This milter also has some callbacks which it does not really use, +** but they are defined to serve as an example. +*/ + +#include +#include +#include +#include +#include +#include + +#include "libmilter/mfapi.h" +#include "libmilter/mfdef.h" + +#ifndef true +# define false 0 +# define true 1 +#endif /* ! true */ + +struct mlfiPriv +{ + char *mlfi_fname; + FILE *mlfi_fp; +}; + +#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx)) + +static unsigned long mta_caps = 0; + +sfsistat +mlfi_cleanup(ctx, ok) + SMFICTX *ctx; + bool ok; +{ + sfsistat rstat = SMFIS_CONTINUE; + struct mlfiPriv *priv = MLFIPRIV; + char *p; + char host[512]; + char hbuf[1024]; + + if (priv == NULL) + return rstat; + + /* close the archive file */ + if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF) + { + /* failed; we have to wait until later */ + rstat = SMFIS_TEMPFAIL; + (void) unlink(priv->mlfi_fname); + } + else if (ok) + { + /* add a header to the message announcing our presence */ + if (gethostname(host, sizeof host) < 0) + snprintf(host, sizeof host, "localhost"); + p = strrchr(priv->mlfi_fname, '/'); + if (p == NULL) + p = priv->mlfi_fname; + else + p++; + snprintf(hbuf, sizeof hbuf, "%s@%s", p, host); + smfi_addheader(ctx, "X-Archived", hbuf); + } + else + { + /* message was aborted -- delete the archive file */ + (void) unlink(priv->mlfi_fname); + } + + /* release private memory */ + free(priv->mlfi_fname); + free(priv); + smfi_setpriv(ctx, NULL); + + /* return status */ + return rstat; +} + + +sfsistat +mlfi_envfrom(ctx, envfrom) + SMFICTX *ctx; + char **envfrom; +{ + struct mlfiPriv *priv; + int fd = -1; + + /* allocate some private memory */ + priv = malloc(sizeof *priv); + if (priv == NULL) + { + /* can't accept this message right now */ + return SMFIS_TEMPFAIL; + } + memset(priv, '\0', sizeof *priv); + + /* open a file to store this message */ + priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX"); + if (priv->mlfi_fname == NULL) + { + free(priv); + return SMFIS_TEMPFAIL; + } + if ((fd = mkstemp(priv->mlfi_fname)) < 0 || + (priv->mlfi_fp = fdopen(fd, "w+")) == NULL) + { + if (fd >= 0) + (void) close(fd); + free(priv->mlfi_fname); + free(priv); + return SMFIS_TEMPFAIL; + } + + /* save the private data */ + smfi_setpriv(ctx, priv); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_header(ctx, headerf, headerv) + SMFICTX *ctx; + char *headerf; + char *headerv; +{ + /* write the header to the log file */ + fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv); + + /* continue processing */ + return ((mta_caps & SMFIP_NR_HDR) != 0) + ? SMFIS_NOREPLY : SMFIS_CONTINUE; +} + +sfsistat +mlfi_eoh(ctx) + SMFICTX *ctx; +{ + /* output the blank line between the header and the body */ + fprintf(MLFIPRIV->mlfi_fp, "\r\n"); + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_body(ctx, bodyp, bodylen) + SMFICTX *ctx; + u_char *bodyp; + size_t bodylen; +{ + /* output body block to log file */ + if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) <= 0) + { + /* write failed */ + (void) mlfi_cleanup(ctx, false); + return SMFIS_TEMPFAIL; + } + + /* continue processing */ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_eom(ctx) + SMFICTX *ctx; +{ + return mlfi_cleanup(ctx, true); +} + +sfsistat +mlfi_close(ctx) + SMFICTX *ctx; +{ + return SMFIS_ACCEPT; +} + +sfsistat +mlfi_abort(ctx) + SMFICTX *ctx; +{ + return mlfi_cleanup(ctx, false); +} + +sfsistat +mlfi_unknown(ctx, cmd) + SMFICTX *ctx; + char *cmd; +{ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_data(ctx) + SMFICTX *ctx; +{ + return SMFIS_CONTINUE; +} + +sfsistat +mlfi_negotiate(ctx, f0, f1, f2, f3, pf0, pf1, pf2, pf3) + SMFICTX *ctx; + unsigned long f0; + unsigned long f1; + unsigned long f2; + unsigned long f3; + unsigned long *pf0; + unsigned long *pf1; + unsigned long *pf2; + unsigned long *pf3; +{ + /* milter actions: add headers */ + *pf0 = SMFIF_ADDHDRS; + + /* milter protocol steps: all but connect, HELO, RCPT */ + *pf1 = SMFIP_NOCONNECT|SMFIP_NOHELO|SMFIP_NORCPT; + mta_caps = f1; + if ((mta_caps & SMFIP_NR_HDR) != 0) + *pf1 |= SMFIP_NR_HDR; + *pf2 = 0; + *pf3 = 0; + return SMFIS_CONTINUE; +} + +struct smfiDesc smfilter = +{ + "SampleFilter", /* filter name */ + SMFI_VERSION, /* version code -- do not change */ + SMFIF_ADDHDRS, /* flags */ + NULL, /* connection info filter */ + NULL, /* SMTP HELO command filter */ + mlfi_envfrom, /* envelope sender filter */ + NULL, /* envelope recipient filter */ + mlfi_header, /* header filter */ + mlfi_eoh, /* end of header */ + mlfi_body, /* body block filter */ + mlfi_eom, /* end of message */ + mlfi_abort, /* message aborted */ + mlfi_close, /* connection cleanup */ + mlfi_unknown, /* unknown/unimplemented SMTP commands */ + mlfi_data, /* DATA command filter */ + mlfi_negotiate /* option negotation at connection startup */ +}; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + bool setconn; + int c; + + setconn = false; + + /* Process command line options */ + while ((c = getopt(argc, argv, "p:")) != -1) + { + switch (c) + { + case 'p': + if (optarg == NULL || *optarg == '\0') + { + (void) fprintf(stderr, "Illegal conn: %s\n", + optarg); + exit(EX_USAGE); + } + (void) smfi_setconn(optarg); + setconn = true; + break; + + } + } + if (!setconn) + { + fprintf(stderr, "%s: Missing required -p argument\n", argv[0]); + exit(EX_USAGE); + } + if (smfi_register(smfilter) == MI_FAILURE) + { + fprintf(stderr, "smfi_register failed\n"); + exit(EX_UNAVAILABLE); + } + return smfi_main(); +} + Property changes on: stable/6/contrib/sendmail/libmilter/example.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/monitor.c =================================================================== --- stable/6/contrib/sendmail/libmilter/monitor.c (nonexistent) +++ stable/6/contrib/sendmail/libmilter/monitor.c (revision 168599) @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include "libmilter.h" + +#if _FFR_THREAD_MONITOR + +/* +** Thread Monitoring +** Todo: more error checking (return code from function calls) +** add comments. +*/ + +bool Monitor = false; /* use monitoring? */ +static unsigned int Mon_exec_time = 0; + +/* mutex protects Mon_cur_ctx, Mon_ctx_head, and ctx_start */ +static smutex_t Mon_mutex; +static scond_t Mon_cv; + +/* +** Current ctx to monitor. +** Invariant: +** Mon_cur_ctx == NULL || Mon_cur_ctx is thread which was started the longest +** time ago. +** +** Basically the entries in the list are ordered by time because new +** entries are appended at the end. However, due to the concurrent +** execution (multi-threaded) and no guaranteed order of wakeups +** after a mutex_lock() attempt, the order might not be strict, +** i.e., if the list contains e1 and e2 (in that order) then +** the the start time of e2 can be (slightly) smaller than that of e1. +** However, this slight inaccurracy should not matter for the proper +** working of this algorithm. +*/ + +static SMFICTX_PTR Mon_cur_ctx = NULL; +static smfi_hd_T Mon_ctx_head; /* head of the linked list of active contexts */ + +/* +** SMFI_SET_MAX_EXEC_TIME -- set maximum execution time for a thread +** +** Parameters: +** tm -- maximum execution time for a thread +** +** Returns: +** MI_SUCCESS +*/ + +int +smfi_set_max_exec_time(tm) + unsigned int tm; +{ + Mon_exec_time = tm; + return MI_SUCCESS; +} + +/* +** MI_MONITOR_THREAD -- monitoring thread +** +** Parameters: +** arg -- ignored (required by pthread_create()) +** +** Returns: +** NULL on termination. +*/ + +static void * +mi_monitor_thread(arg) + void *arg; +{ + sthread_t tid; + int r; + time_t now, end; + + SM_ASSERT(Monitor); + SM_ASSERT(Mon_exec_time > 0); + tid = (sthread_t) sthread_get_id(); + if (pthread_detach(tid) != 0) + { + /* log an error */ + return (void *)1; + } + +/* +** NOTE: this is "flow through" code, +** do NOT use do { } while ("break" is used here!) +*/ + +#define MON_CHK_STOP \ + now = time(NULL); \ + end = Mon_cur_ctx->ctx_start + Mon_exec_time; \ + if (now > end) \ + { \ + smi_log(SMI_LOG_ERR, \ + "WARNING: monitor timeout triggered, now=%ld, end=%ld, tid=%ld, state=0x%x",\ + (long) now, (long) end, \ + (long) Mon_cur_ctx->ctx_id, Mon_cur_ctx->ctx_state);\ + mi_stop_milters(MILTER_STOP); \ + break; \ + } + + (void) smutex_lock(&Mon_mutex); + while (mi_stop() == MILTER_CONT) + { + if (Mon_cur_ctx != NULL && Mon_cur_ctx->ctx_start > 0) + { + struct timespec abstime; + + MON_CHK_STOP; + abstime.tv_sec = end; + abstime.tv_nsec = 0; + r = pthread_cond_timedwait(&Mon_cv, &Mon_mutex, + &abstime); + } + else + r = pthread_cond_wait(&Mon_cv, &Mon_mutex); + if (mi_stop() != MILTER_CONT) + break; + if (Mon_cur_ctx != NULL && Mon_cur_ctx->ctx_start > 0) + { + MON_CHK_STOP; + } + } + (void) smutex_unlock(&Mon_mutex); + + return NULL; +} + +/* +** MI_MONITOR_INIT -- initialize monitoring thread +** +** Parameters: none +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +mi_monitor_init() +{ + int r; + sthread_t tid; + + SM_ASSERT(!Monitor); + if (Mon_exec_time <= 0) + return MI_SUCCESS; + Monitor = true; + if (!smutex_init(&Mon_mutex)) + return MI_FAILURE; + if (scond_init(&Mon_cv) != 0) + return MI_FAILURE; + SM_TAILQ_INIT(&Mon_ctx_head); + + r = thread_create(&tid, mi_monitor_thread, (void *)NULL); + if (r != 0) + return r; + return MI_SUCCESS; +} + +/* +** MI_MONITOR_WORK_BEGIN -- record start of thread execution +** +** Parameters: +** ctx -- session context +** cmd -- milter command char +** +** Returns: +** 0 +*/ + +int +mi_monitor_work_begin(ctx, cmd) + SMFICTX_PTR ctx; + int cmd; +{ + (void) smutex_lock(&Mon_mutex); + if (NULL == Mon_cur_ctx) + { + Mon_cur_ctx = ctx; + (void) scond_signal(&Mon_cv); + } + ctx->ctx_start = time(NULL); + SM_TAILQ_INSERT_TAIL(&Mon_ctx_head, ctx, ctx_mon_link); + (void) smutex_unlock(&Mon_mutex); + return 0; +} + +/* +** MI_MONITOR_WORK_END -- record end of thread execution +** +** Parameters: +** ctx -- session context +** cmd -- milter command char +** +** Returns: +** 0 +*/ + +int +mi_monitor_work_end(ctx, cmd) + SMFICTX_PTR ctx; + int cmd; +{ + (void) smutex_lock(&Mon_mutex); + ctx->ctx_start = 0; + SM_TAILQ_REMOVE(&Mon_ctx_head, ctx, ctx_mon_link); + if (Mon_cur_ctx == ctx) + { + if (SM_TAILQ_EMPTY(&Mon_ctx_head)) + Mon_cur_ctx = NULL; + else + Mon_cur_ctx = SM_TAILQ_FIRST(&Mon_ctx_head); + } + (void) smutex_unlock(&Mon_mutex); + return 0; +} +#endif /* _FFR_THREAD_MONITOR */ Property changes on: stable/6/contrib/sendmail/libmilter/monitor.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libmilter/worker.c =================================================================== --- stable/6/contrib/sendmail/libmilter/worker.c (nonexistent) +++ stable/6/contrib/sendmail/libmilter/worker.c (revision 168599) @@ -0,0 +1,792 @@ +/* + * Copyright (c) 2003-2004, 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * Contributed by Jose Marcio Martins da Cruz - Ecole des Mines de Paris + * Jose-Marcio.Martins@ensmp.fr + */ + +#include +SM_RCSID("@(#)$Id: worker.c,v 8.9 2006/12/18 18:26:51 ca Exp $") + +#include "libmilter.h" + +#if _FFR_WORKERS_POOL + +typedef struct taskmgr_S taskmgr_T; + +#define TM_SIGNATURE 0x23021957 + +struct taskmgr_S +{ + long tm_signature; /* has the controller been initialized */ + sthread_t tm_tid; /* thread id of controller */ + smfi_hd_T tm_ctx_head; /* head of the linked list of contexts */ + + int tm_nb_workers; /* number of workers in the pool */ + int tm_nb_idle; /* number of workers waiting */ + + int tm_p[2]; /* poll control pipe */ + + smutex_t tm_w_mutex; /* linked list access mutex */ + scond_t tm_w_cond; /* */ +}; + +static taskmgr_T Tskmgr = {0}; + +#define WRK_CTX_HEAD Tskmgr.tm_ctx_head + +#define RD_PIPE (Tskmgr.tm_p[0]) +#define WR_PIPE (Tskmgr.tm_p[1]) + +#define PIPE_SEND_SIGNAL() \ + do \ + { \ + char evt = 0x5a; \ + int fd = WR_PIPE; \ + if (write(fd, &evt, sizeof(evt)) != sizeof(evt)) \ + smi_log(SMI_LOG_ERR, \ + "Error writing to event pipe: %s", \ + sm_errstring(errno)); \ + } while (0) + +#ifndef USE_PIPE_WAKE_POLL +# define USE_PIPE_WAKE_POLL 1 +#endif /* USE_PIPE_WAKE_POLL */ + +/* poll check periodicity (default 10000 - 10 s) */ +#define POLL_TIMEOUT 10000 + +/* worker conditional wait timeout (default 10 s) */ +#define COND_TIMEOUT 10 + +/* functions */ +static int mi_close_session __P((SMFICTX_PTR)); + +static void *mi_worker __P((void *)); +static void *mi_pool_controller __P((void *)); + +static int mi_list_add_ctx __P((SMFICTX_PTR)); +static int mi_list_del_ctx __P((SMFICTX_PTR)); + +/* +** periodicity of cleaning up old sessions (timedout) +** sessions list will be checked to find old inactive +** sessions each DT_CHECK_OLD_SESSIONS sec +*/ + +#define DT_CHECK_OLD_SESSIONS 600 + +#ifndef OLD_SESSION_TIMEOUT +# define OLD_SESSION_TIMEOUT ctx->ctx_timeout +#endif /* OLD_SESSION_TIMEOUT */ + +/* session states - with respect to the pool of workers */ +#define WKST_INIT 0 /* initial state */ +#define WKST_READY_TO_RUN 1 /* command ready do be read */ +#define WKST_RUNNING 2 /* session running on a worker */ +#define WKST_READY_TO_WAIT 3 /* session just finished by a worker */ +#define WKST_WAITING 4 /* waiting for new command */ +#define WKST_CLOSING 5 /* session finished */ + +#ifndef MIN_WORKERS +# define MIN_WORKERS 2 /* minimum number of threads to keep around */ +#endif + +#define MIN_IDLE 1 /* minimum number of idle threads */ + + +/* +** Macros for threads and mutex management +*/ + +#define TASKMGR_LOCK() \ + do \ + { \ + if (!smutex_lock(&Tskmgr.tm_w_mutex)) \ + smi_log(SMI_LOG_ERR, "TASKMGR_LOCK error"); \ + } while (0) + +#define TASKMGR_UNLOCK() \ + do \ + { \ + if (!smutex_unlock(&Tskmgr.tm_w_mutex)) \ + smi_log(SMI_LOG_ERR, "TASKMGR_UNLOCK error"); \ + } while (0) + +#define TASKMGR_COND_WAIT() \ + scond_timedwait(&Tskmgr.tm_w_cond, &Tskmgr.tm_w_mutex, COND_TIMEOUT) + +#define TASKMGR_COND_SIGNAL() \ + do \ + { \ + if (scond_signal(&Tskmgr.tm_w_cond) != 0) \ + smi_log(SMI_LOG_ERR, "TASKMGR_COND_SIGNAL error"); \ + } while (0) + +#define LAUNCH_WORKER(ctx) \ + do \ + { \ + int r; \ + sthread_t tid; \ + \ + if ((r = thread_create(&tid, mi_worker, ctx)) != 0) \ + smi_log(SMI_LOG_ERR, "LAUNCH_WORKER error: %s",\ + sm_errstring(r)); \ + } while (0) + +#if POOL_DEBUG +# define POOL_LEV_DPRINTF(lev, x) \ + do { \ + if ((lev) < ctx->ctx_dbg) \ + sm_dprintf x; \ + } while (0) +#else /* POOL_DEBUG */ +# define POOL_LEV_DPRINTF(lev, x) +#endif /* POOL_DEBUG */ + +/* +** MI_START_SESSION -- Start a session in the pool of workers +** +** Parameters: +** ctx -- context structure +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +mi_start_session(ctx) + SMFICTX_PTR ctx; +{ + static long id = 0; + + SM_ASSERT(Tskmgr.tm_signature == TM_SIGNATURE); + SM_ASSERT(ctx != NULL); + POOL_LEV_DPRINTF(4, ("PIPE r=[%d] w=[%d]", RD_PIPE, WR_PIPE)); + TASKMGR_LOCK(); + + if (mi_list_add_ctx(ctx) != MI_SUCCESS) + { + TASKMGR_UNLOCK(); + return MI_FAILURE; + } + + ctx->ctx_sid = id++; + + /* if there is an idle worker, signal it, otherwise start new worker */ + if (Tskmgr.tm_nb_idle > 0) + { + ctx->ctx_wstate = WKST_READY_TO_RUN; + TASKMGR_COND_SIGNAL(); + } + else + { + ctx->ctx_wstate = WKST_RUNNING; + LAUNCH_WORKER(ctx); + } + TASKMGR_UNLOCK(); + return MI_SUCCESS; +} + +/* +** MI_CLOSE_SESSION -- Close a session and clean up data structures +** +** Parameters: +** ctx -- context structure +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +static int +mi_close_session(ctx) + SMFICTX_PTR ctx; +{ + SM_ASSERT(ctx != NULL); + + (void) mi_list_del_ctx(ctx); + if (ValidSocket(ctx->ctx_sd)) + { + (void) closesocket(ctx->ctx_sd); + ctx->ctx_sd = INVALID_SOCKET; + } + if (ctx->ctx_reply != NULL) + { + free(ctx->ctx_reply); + ctx->ctx_reply = NULL; + } + if (ctx->ctx_privdata != NULL) + { + smi_log(SMI_LOG_WARN, "%s: private data not NULL", + ctx->ctx_smfi->xxfi_name); + } + mi_clr_macros(ctx, 0); + free(ctx); + + return MI_SUCCESS; +} + +/* +** MI_POOL_CONTROLER_INIT -- Launch the worker pool controller +** Must be called before starting sessions. +** +** Parameters: +** none +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +mi_pool_controller_init() +{ + sthread_t tid; + int r, i; + + if (Tskmgr.tm_signature == TM_SIGNATURE) + return MI_SUCCESS; + + SM_TAILQ_INIT(&WRK_CTX_HEAD); + Tskmgr.tm_tid = (sthread_t) -1; + Tskmgr.tm_nb_workers = 0; + Tskmgr.tm_nb_idle = 0; + + if (pipe(Tskmgr.tm_p) != 0) + { + smi_log(SMI_LOG_ERR, "can't create event pipe: %s", + sm_errstring(r)); + return MI_FAILURE; + } + + POOL_LEV_DPRINTF(4, ("PIPE r=[%d] w=[%d]", RD_PIPE, WR_PIPE)); + + (void) smutex_init(&Tskmgr.tm_w_mutex); + (void) scond_init(&Tskmgr.tm_w_cond); + + /* Launch the pool controller */ + if ((r = thread_create(&tid, mi_pool_controller, (void *) NULL)) != 0) + { + smi_log(SMI_LOG_ERR, "can't create controller thread: %s", + sm_errstring(r)); + return MI_FAILURE; + } + Tskmgr.tm_tid = tid; + Tskmgr.tm_signature = TM_SIGNATURE; + + /* Create the pool of workers */ + for (i = 0; i < MIN_WORKERS; i++) + { + if ((r = thread_create(&tid, mi_worker, (void *) NULL)) != 0) + { + smi_log(SMI_LOG_ERR, "can't create workers crew: %s", + sm_errstring(r)); + return MI_FAILURE; + } + } + + return MI_SUCCESS; +} + +/* +** MI_POOL_CONTROLLER -- manage the pool of workers +** This thread must be running when listener begins +** starting sessions +** +** Parameters: +** arg -- unused +** +** Returns: +** NULL +** +** Control flow: +** for (;;) +** Look for timed out sessions +** Select sessions to wait for sendmail command +** Poll set of file descriptors +** if timeout +** continue +** For each file descriptor ready +** launch new thread if no worker available +** else +** signal waiting worker +*/ + +/* Poll structure array (pollfd) size step */ +#define PFD_STEP 256 + +#define WAIT_FD(i) (pfd[i].fd) +#define WAITFN "POLL" + +static void * +mi_pool_controller(arg) + void *arg; +{ + struct pollfd *pfd = NULL; + int dim_pfd = 0; + bool rebuild_set = true; + int pcnt = 0; /* error count for poll() failures */ + + Tskmgr.tm_tid = sthread_get_id(); + if (pthread_detach(Tskmgr.tm_tid) != 0) + { + smi_log(SMI_LOG_ERR, "Failed to detach pool controller thread"); + return NULL; + } + + pfd = (struct pollfd *) malloc(PFD_STEP * sizeof(struct pollfd)); + if (pfd == NULL) + { + smi_log(SMI_LOG_ERR, "Failed to malloc pollfd array: %s", + sm_errstring(errno)); + return NULL; + } + dim_pfd = PFD_STEP; + + for (;;) + { + SMFICTX_PTR ctx; + int nfd, rfd, i; + time_t now; + time_t lastcheck; + + POOL_LEV_DPRINTF(4, ("Let's %s again...", WAITFN)); + + if (mi_stop() != MILTER_CONT) + break; + + TASKMGR_LOCK(); + + now = time(NULL); + + /* check for timed out sessions? */ + if (lastcheck + DT_CHECK_OLD_SESSIONS < now) + { + SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link) + { + if (ctx->ctx_wstate == WKST_WAITING) + { + if (ctx->ctx_wait == 0) + { + ctx->ctx_wait = now; + continue; + } + + /* if session timed out, close it */ + if (ctx->ctx_wait + OLD_SESSION_TIMEOUT + < now) + { + sfsistat (*fi_close) __P((SMFICTX *)); + + POOL_LEV_DPRINTF(4, + ("Closing old connection: sd=%d id=%d", + ctx->ctx_sd, + ctx->ctx_sid)); + + if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) + (void) (*fi_close)(ctx); + + mi_close_session(ctx); + ctx = SM_TAILQ_FIRST(&WRK_CTX_HEAD); + continue; + } + } + } + lastcheck = now; + } + + if (rebuild_set) + { + /* + ** Initialize poll set. + ** Insert into the poll set the file descriptors of + ** all sessions waiting for a command from sendmail. + */ + + nfd = 0; + + /* begin with worker pipe */ + pfd[nfd].fd = RD_PIPE; + pfd[nfd].events = MI_POLL_RD_FLAGS; + pfd[nfd].revents = 0; + nfd++; + + SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link) + { + /* + ** update ctx_wait - start of wait moment - + ** for timeout + */ + + if (ctx->ctx_wstate == WKST_READY_TO_WAIT) + ctx->ctx_wait = now; + + /* add the session to the pollfd array? */ + if ((ctx->ctx_wstate == WKST_READY_TO_WAIT) || + (ctx->ctx_wstate == WKST_WAITING)) + { + /* + ** Resize the pollfd array if it + ** isn't large enough. + */ + + if (nfd >= dim_pfd) + { + struct pollfd *tpfd; + size_t new; + + new = (dim_pfd + PFD_STEP) * + sizeof(*tpfd); + tpfd = (struct pollfd *) + realloc(pfd, new); + if (tpfd != NULL) + { + pfd = tpfd; + dim_pfd += PFD_STEP; + } + else + { + smi_log(SMI_LOG_ERR, + "Failed to realloc pollfd array:%s", + sm_errstring(errno)); + } + } + + /* add the session to pollfd array */ + if (nfd < dim_pfd) + { + ctx->ctx_wstate = WKST_WAITING; + pfd[nfd].fd = ctx->ctx_sd; + pfd[nfd].events = MI_POLL_RD_FLAGS; + pfd[nfd].revents = 0; + nfd++; + } + } + } + } + + TASKMGR_UNLOCK(); + + /* Everything is ready, let's wait for an event */ + rfd = poll(pfd, nfd, POLL_TIMEOUT); + + POOL_LEV_DPRINTF(4, ("%s returned: at epoch %d value %d", + WAITFN, now, nfd)); + + /* timeout */ + if (rfd == 0) + continue; + + rebuild_set = true; + + /* error */ + if (rfd < 0) + { + if (errno == EINTR) + continue; + pcnt++; + smi_log(SMI_LOG_ERR, + "%s() failed (%s), %s", + WAITFN, sm_errstring(errno), + pcnt >= MAX_FAILS_S ? "abort" : "try again"); + + if (pcnt >= MAX_FAILS_S) + goto err; + } + pcnt = 0; + + /* something happened */ + for (i = 0; i < nfd; i++) + { + if (pfd[i].revents == 0) + continue; + + POOL_LEV_DPRINTF(4, ("%s event on pfd[%d/%d]=%d ", + WAITFN, i, nfd, + WAIT_FD(i))); + + /* has a worker signaled an end of task ? */ + if (WAIT_FD(i) == RD_PIPE) + { + char evt = 0; + int r = 0; + + POOL_LEV_DPRINTF(4, + ("PIPE WILL READ evt = %08X %08X", + pfd[i].events, pfd[i].revents)); + + if ((pfd[i].revents & MI_POLL_RD_FLAGS) != 0) + { + r = read(RD_PIPE, &evt, sizeof(evt)); + if (r == sizeof(evt)) + { + /* Do nothing */ + } + } + + POOL_LEV_DPRINTF(4, + ("PIPE DONE READ i=[%d] fd=[%d] r=[%d] evt=[%d]", + i, RD_PIPE, r, evt)); + + if ((pfd[i].revents & ~MI_POLL_RD_FLAGS) != 0) + { + /* Exception handling */ + } + continue; + } + + /* no ! sendmail wants to send a command */ + SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link) + { + if (ctx->ctx_wstate != WKST_WAITING) + continue; + + POOL_LEV_DPRINTF(4, + ("Checking context sd=%d - fd=%d ", + ctx->ctx_sd , WAIT_FD(i))); + + if (ctx->ctx_sd == pfd[i].fd) + { + TASKMGR_LOCK(); + + POOL_LEV_DPRINTF(4, + ("TASK: found %d for fd[%d]=%d", + ctx->ctx_sid, i, WAIT_FD(i))); + + if (Tskmgr.tm_nb_idle > 0) + { + ctx->ctx_wstate = WKST_READY_TO_RUN; + TASKMGR_COND_SIGNAL(); + } + else + { + ctx->ctx_wstate = WKST_RUNNING; + LAUNCH_WORKER(ctx); + } + TASKMGR_UNLOCK(); + break; + } + } + + POOL_LEV_DPRINTF(4, + ("TASK %s FOUND - Checking PIPE for fd[%d]", + ctx != NULL ? "" : "NOT", WAIT_FD(i))); + } + } + + err: + if (pfd != NULL) + free(pfd); + + Tskmgr.tm_signature = 0; + for (;;) + { + SMFICTX_PTR ctx; + + ctx = SM_TAILQ_FIRST(&WRK_CTX_HEAD); + if (ctx == NULL) + break; + mi_close_session(ctx); + } + + (void) smutex_destroy(&Tskmgr.tm_w_mutex); + (void) scond_destroy(&Tskmgr.tm_w_cond); + + return NULL; +} + +/* +** Look for a task ready to run. +** Value of ctx is NULL or a pointer to a task ready to run. +*/ + +#define GET_TASK_READY_TO_RUN() \ + SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link) \ + { \ + if (ctx->ctx_wstate == WKST_READY_TO_RUN) \ + { \ + ctx->ctx_wstate = WKST_RUNNING; \ + break; \ + } \ + } + +/* +** MI_WORKER -- worker thread +** executes tasks distributed by the mi_pool_controller +** or by mi_start_session +** +** Parameters: +** arg -- pointer to context structure +** +** Returns: +** NULL pointer +*/ + +static void * +mi_worker(arg) + void *arg; +{ + SMFICTX_PTR ctx; + bool done; + sthread_t t_id; + int r; + + ctx = (SMFICTX_PTR) arg; + done = false; + if (ctx != NULL) + ctx->ctx_wstate = WKST_RUNNING; + + t_id = sthread_get_id(); + if (pthread_detach(t_id) != 0) + { + smi_log(SMI_LOG_ERR, "Failed to detach worker thread"); + if (ctx != NULL) + ctx->ctx_wstate = WKST_READY_TO_RUN; + return NULL; + } + + TASKMGR_LOCK(); + Tskmgr.tm_nb_workers++; + TASKMGR_UNLOCK(); + + while (!done) + { + if (mi_stop() != MILTER_CONT) + break; + + /* let's handle next task... */ + if (ctx != NULL) + { + int res; + + POOL_LEV_DPRINTF(4, + ("worker %d: new task -> let's handle it", + t_id)); + res = mi_engine(ctx); + POOL_LEV_DPRINTF(4, + ("worker %d: mi_engine returned %d", t_id, res)); + + TASKMGR_LOCK(); + if (res != MI_CONTINUE) + { + ctx->ctx_wstate = WKST_CLOSING; + + /* + ** Delete context from linked list of + ** sessions and close session. + */ + + mi_close_session(ctx); + } + else + { + ctx->ctx_wstate = WKST_READY_TO_WAIT; + + POOL_LEV_DPRINTF(4, + ("writing to event pipe...")); + + /* + ** Signal task controller to add new session + ** to poll set. + */ + + PIPE_SEND_SIGNAL(); + } + TASKMGR_UNLOCK(); + ctx = NULL; + + } + + /* check if there is any task waiting to be served */ + TASKMGR_LOCK(); + + GET_TASK_READY_TO_RUN(); + + /* Got a task? */ + if (ctx != NULL) + { + TASKMGR_UNLOCK(); + continue; + } + + /* + ** if not, let's check if there is enough idle workers + ** if yes: quit + */ + + if (Tskmgr.tm_nb_workers > MIN_WORKERS && + Tskmgr.tm_nb_idle > MIN_IDLE) + done = true; + + POOL_LEV_DPRINTF(4, ("worker %d: checking ... %d %d", t_id, + Tskmgr.tm_nb_workers, Tskmgr.tm_nb_idle + 1)); + + if (done) + { + POOL_LEV_DPRINTF(4, ("worker %d: quitting... ", t_id)); + Tskmgr.tm_nb_workers--; + TASKMGR_UNLOCK(); + continue; + } + + /* + ** if no task ready to run, wait for another one + */ + + Tskmgr.tm_nb_idle++; + TASKMGR_COND_WAIT(); + Tskmgr.tm_nb_idle--; + + /* look for a task */ + GET_TASK_READY_TO_RUN(); + + TASKMGR_UNLOCK(); + } + return NULL; +} + +/* +** MI_LIST_ADD_CTX -- add new session to linked list +** +** Parameters: +** ctx -- context structure +** +** Returns: +** MI_FAILURE/MI_SUCCESS +*/ + +static int +mi_list_add_ctx(ctx) + SMFICTX_PTR ctx; +{ + SM_ASSERT(ctx != NULL); + SM_TAILQ_INSERT_TAIL(&WRK_CTX_HEAD, ctx, ctx_link); + return MI_SUCCESS; +} + +/* +** MI_LIST_DEL_CTX -- remove session from linked list when finished +** +** Parameters: +** ctx -- context structure +** +** Returns: +** MI_FAILURE/MI_SUCCESS +*/ + +static int +mi_list_del_ctx(ctx) + SMFICTX_PTR ctx; +{ + SM_ASSERT(ctx != NULL); + if (SM_TAILQ_EMPTY(&WRK_CTX_HEAD)) + return MI_FAILURE; + + SM_TAILQ_REMOVE(&WRK_CTX_HEAD, ctx, ctx_link); + return MI_SUCCESS; +} +#endif /* _FFR_WORKERS_POOL */ Property changes on: stable/6/contrib/sendmail/libmilter/worker.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libsm/t-qic.c =================================================================== --- stable/6/contrib/sendmail/libsm/t-qic.c (nonexistent) +++ stable/6/contrib/sendmail/libsm/t-qic.c (revision 168599) @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +#include +SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.9 2006/08/24 21:26:13 ca Exp $") + +#include +#include +#include +#include +#include +#include + +extern bool SmTestVerbose; + + +void +show_diff(s1, s2) + const char *s1; + const char *s2; +{ + int i; + + for (i = 0; s1[i] != '\0' && s2[i] != '\0'; i++) + { + if (s1[i] != s2[i]) + { + fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n", + i, (unsigned char) s1[i], + (unsigned char) s2[i]); + return; + } + } + if (s1[i] != s2[i]) + { + fprintf(stderr, "i=%d, s1[]=%u, s2[]=%u\n", + i, (unsigned char) s1[i], (unsigned char) s2[i]); + } +} + +char *quote_unquote __P((char *, char *, int, int)); + +char * +quote_unquote(in, out, outlen, exp) + char *in; + char *out; + int outlen; + int exp; +{ + char *obp, *bp; + char line_back[1024]; + char line_in[1024]; + int cmp; + + sm_strlcpy(line_in, in, sizeof(line_in)); + obp = quote_internal_chars(in, out, &outlen); + bp = str2prt(line_in); + dequote_internal_chars(obp, line_back, sizeof(line_back)); + cmp = strcmp(line_in, line_back); + SM_TEST(exp == cmp); + if (cmp != exp && !SmTestVerbose) + { + fprintf(stderr, "in: %s\n", bp); + bp = str2prt(line_back); + fprintf(stderr, "out:%s\n", bp); + fprintf(stderr, "cmp=%d\n", cmp); + show_diff(in, line_back); + } + if (SmTestVerbose) + { + fprintf(stderr, "%s -> ", bp); + bp = str2prt(obp); + fprintf(stderr, "%s\n", bp); + fprintf(stderr, "cmp=%d\n", cmp); + } + return obp; +} + +struct sm_qic_S +{ + char *qic_in; + char *qic_out; + int qic_exp; +}; + +typedef struct sm_qic_S sm_qic_T; + + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char line_in[1024], line[256], line_out[32], *obp; + int i, los, cmp; + sm_qic_T inout[] = { + { "", "", 0 } + , { "abcdef", "abcdef", 0 } + , { "01234567890123456789", "01234567890123456789", 0 } + , { "01234567890123456789\001", "01234567890123456789\001", + 0 } + , { "012345\2067890123456789", "012345\377\2067890123456789", + 0 } + , { "\377", "\377\377", 0 } + , { "\240", "\240", 0 } + , { "\220", "\377\220", 0 } + , { "\240\220", "\240\377\220", 0 } + , { "\377\377", "\377\377\377\377", 0 } + , { "\377a\377b", "\377\377a\377\377b", 0 } + , { "\376a\377b", "\376a\377\377b", 0 } + , { "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237\240", + "\377\200\377\201\377\202\377\203\377\204\377\205\377\206\377\207\377\210\377\211\377\212\377\213\377\214\377\215\377\216\377\217\377\220\377\221\377\222\377\223\377\224\377\225\377\226\377\227\377\230\377\231\377\232\377\233\377\234\377\235\377\236\377\237\240", + 0 } + , { NULL, NULL, 0 } + }; + + sm_test_begin(argc, argv, "test meta quoting"); + for (i = 0; i < sizeof(line_out); i++) + line_out[i] = '\0'; + for (i = 0; i < sizeof(line_in); i++) + line_in[i] = '\0'; + for (i = 0; i < sizeof(line_in) / 2; i++) + { + char ch; + + ch = 0200 + i; + if ('\0' == ch) + ch = '0'; + line_in[i] = ch; + } + los = sizeof(line_out) / 2; + obp = quote_unquote(line_in, line_out, los, 0); + if (obp != line_out) + SM_FREE(obp); + + for (i = 0; i < sizeof(line_in); i++) + line_in[i] = '\0'; + for (i = 0; i < sizeof(line_in) / 2; i++) + { + char ch; + + ch = 0200 + i; + if ('\0' == ch) + ch = '0'; + line_in[i] = ch; + } + los = sizeof(line_in); + obp = quote_unquote(line_in, line_in, los, 0); + if (obp != line_in) + SM_FREE(obp); + + for (i = 0; inout[i].qic_in != NULL; i++) + { + los = sizeof(line_out) / 2; + obp = quote_unquote(inout[i].qic_in, line_out, los, + inout[i].qic_exp); + cmp = strcmp(inout[i].qic_out, obp); + SM_TEST(inout[i].qic_exp == cmp); + if (inout[i].qic_exp != cmp && !SmTestVerbose) + { + char *bp; + + bp = str2prt(obp); + fprintf(stderr, "got: %s\n", bp); + bp = str2prt(inout[i].qic_out); + fprintf(stderr, "exp:%s\n", bp); + fprintf(stderr, "cmp=%d\n", cmp); + show_diff(inout[i].qic_in, inout[i].qic_out); + } + if (obp != line_out) + SM_FREE(obp); + } + + /* use same buffer for in and out */ + for (i = 0; inout[i].qic_in != NULL; i++) + { + bool same; + + same = strcmp(inout[i].qic_in, inout[i].qic_out) == 0; + los = sm_strlcpy(line, inout[i].qic_in, sizeof(line)); + SM_TEST(los + 1 < sizeof(line)); + ++los; + obp = quote_unquote(line, line, los, inout[i].qic_exp); + cmp = strcmp(inout[i].qic_out, obp); + SM_TEST(inout[i].qic_exp == cmp); + if (inout[i].qic_exp != cmp && !SmTestVerbose) + { + char *bp; + + bp = str2prt(obp); + fprintf(stderr, "got: %s\n", bp); + bp = str2prt(inout[i].qic_out); + fprintf(stderr, "exp:%s\n", bp); + fprintf(stderr, "cmp=%d\n", cmp); + show_diff(inout[i].qic_in, inout[i].qic_out); + } + if (obp != line) + { + SM_TEST(!same); + if (same) + show_diff(obp, inout[i].qic_out); + SM_FREE(obp); + } + } + + /* use NULL buffer for out */ + for (i = 0; inout[i].qic_in != NULL; i++) + { + los = 0; + obp = quote_unquote(inout[i].qic_in, NULL, los, + inout[i].qic_exp); + SM_TEST(obp != NULL); + cmp = strcmp(inout[i].qic_out, obp); + SM_TEST(inout[i].qic_exp == cmp); + if (inout[i].qic_exp != cmp && !SmTestVerbose) + { + char *bp; + + bp = str2prt(obp); + fprintf(stderr, "got: %s\n", bp); + bp = str2prt(inout[i].qic_out); + fprintf(stderr, "exp:%s\n", bp); + fprintf(stderr, "cmp=%d\n", cmp); + show_diff(inout[i].qic_in, inout[i].qic_out); + } + } + + return sm_test_end(); +} Property changes on: stable/6/contrib/sendmail/libsm/t-qic.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/libsm/util.c =================================================================== --- stable/6/contrib/sendmail/libsm/util.c (nonexistent) +++ stable/6/contrib/sendmail/libsm/util.c (revision 168599) @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + */ + +#include + +SM_RCSID("@(#)$Id: util.c,v 1.9 2006/08/30 18:35:51 ca Exp $") +#include +#include +#include +#include +#include +#include +#include + +/* +** STR2PRT -- convert "unprintable" characters in a string to \oct +** +** Parameters: +** s -- string to convert +** +** Returns: +** converted string. +** This is a static local buffer, string must be copied +** before this function is called again! +*/ + +char * +str2prt(s) + char *s; +{ + int l; + char c, *h; + bool ok; + static int len = 0; + static char *buf = NULL; + + if (s == NULL) + return NULL; + ok = true; + for (h = s, l = 1; *h != '\0'; h++, l++) + { + if (*h == '\\') + { + ++l; + ok = false; + } + else if (!(isascii(*h) && isprint(*h))) + { + l += 3; + ok = false; + } + } + if (ok) + return s; + if (l > len) + { + char *nbuf = sm_pmalloc_x(l); + + if (buf != NULL) + sm_free(buf); + len = l; + buf = nbuf; + } + for (h = buf; *s != '\0' && l > 0; s++, l--) + { + c = *s; + if (isascii(c) && isprint(c) && c != '\\') + { + *h++ = c; + } + else + { + *h++ = '\\'; + --l; + switch (c) + { + case '\\': + *h++ = '\\'; + break; + case '\t': + *h++ = 't'; + break; + case '\n': + *h++ = 'n'; + break; + case '\r': + *h++ = 'r'; + break; + default: + SM_ASSERT(l >= 2); + (void) sm_snprintf(h, l, "%03o", + (unsigned int)((unsigned char) c)); + + /* + ** XXX since l is unsigned this may + ** wrap around if the calculation is screwed + ** up... + */ + + l -= 2; + h += 3; + break; + } + } + } + *h = '\0'; + buf[len - 1] = '\0'; + return buf; +} + +/* +** QUOTE_INTERNAL_CHARS -- do quoting of internal characters +** +** Necessary to make sure that we don't have metacharacters such +** as the internal versions of "$*" or "$&" in a string. +** The input and output pointers can be the same. +** +** Parameters: +** ibp -- a pointer to the string to translate +** obp -- a pointer to an output buffer +** bsp -- pointer to the length of the output buffer +** +** Returns: +** A possibly new bp (if the buffer needed to grow); if +** it is different, *bsp will updated to the size of +** the new buffer and the caller is responsible for +** freeing the memory. +*/ + +#define SM_MM_QUOTE(ch) (((ch) & 0377) == METAQUOTE || (((ch) & 0340) == 0200)) + +char * +quote_internal_chars(ibp, obp, bsp) + char *ibp; + char *obp; + int *bsp; +{ + char *ip, *op; + int bufused, olen; + bool buffer_same, needs_quoting; + + buffer_same = ibp == obp; + needs_quoting = false; + + /* determine length of output string (starts at 1 for trailing '\0') */ + for (ip = ibp, olen = 1; *ip != '\0'; ip++, olen++) + { + if (SM_MM_QUOTE(*ip)) + { + olen++; + needs_quoting = true; + } + } + + /* is the output buffer big enough? */ + if (olen > *bsp) + { + obp = sm_malloc_x(olen); + buffer_same = false; + *bsp = olen; + } + + /* + ** shortcut: no change needed? + ** Note: we don't check this first as some bozo may use the same + ** buffers but restrict the size of the output buffer to less + ** than the length of the input buffer in which case we need to + ** allocate a new buffer. + */ + + if (!needs_quoting) + { + if (!buffer_same) + { + bufused = sm_strlcpy(obp, ibp, *bsp); + SM_ASSERT(bufused <= olen); + } + return obp; + } + + if (buffer_same) + { + obp = sm_malloc_x(olen); + buffer_same = false; + *bsp = olen; + } + + for (ip = ibp, op = obp, bufused = 0; *ip != '\0'; ip++) + { + if (SM_MM_QUOTE(*ip)) + { + SM_ASSERT(bufused < olen); + op[bufused++] = METAQUOTE; + } + SM_ASSERT(bufused < olen); + op[bufused++] = *ip; + } + op[bufused] = '\0'; + return obp; +} + +/* +** DEQUOTE_INTERNAL_CHARS -- undo the effect of quote_internal_chars +** +** Parameters: +** ibp -- a pointer to the string to be translated. +** obp -- a pointer to the output buffer. Can be the +** same as ibp. +** obs -- the size of the output buffer. +** +** Returns: +** number of character added to obp +*/ + +int +dequote_internal_chars(ibp, obp, obs) + char *ibp; + char *obp; + int obs; +{ + char *ip, *op; + int len; + bool quoted; + + quoted = false; + len = 0; + for (ip = ibp, op = obp; *ip != '\0'; ip++) + { + if ((*ip & 0377) == METAQUOTE && !quoted) + { + quoted = true; + continue; + } + if (op < &obp[obs - 1]) + { + *op++ = *ip; + ++len; + } + quoted = false; + } + *op = '\0'; + return len; +} Property changes on: stable/6/contrib/sendmail/libsm/util.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/src/daemon.h =================================================================== --- stable/6/contrib/sendmail/src/daemon.h (nonexistent) +++ stable/6/contrib/sendmail/src/daemon.h (revision 168599) @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Id: daemon.h,v 8.3 2006/07/13 22:57:03 ca Exp $ + */ + +#ifndef DAEMON_H +#define DAEMON_H 1 + +#if DAEMON_C +# define EXTERN +#else +# define EXTERN extern +#endif + +/* structure to describe a daemon or a client */ +struct daemon +{ + int d_socket; /* fd for socket */ + SOCKADDR d_addr; /* socket for incoming */ + unsigned short d_port; /* port number */ + int d_listenqueue; /* size of listen queue */ + int d_tcprcvbufsize; /* size of TCP receive buffer */ + int d_tcpsndbufsize; /* size of TCP send buffer */ + time_t d_refuse_connections_until; + bool d_firsttime; + int d_socksize; + BITMAP256 d_flags; /* flags; see sendmail.h */ + char *d_mflags; /* flags for use in macro */ + char *d_name; /* user-supplied name */ + + int d_dm; /* DeliveryMode */ + int d_refuseLA; + int d_queueLA; + int d_delayLA; + int d_maxchildren; + +#if MILTER + char *d_inputfilterlist; + struct milter *d_inputfilters[MAXFILTERS]; +#endif /* MILTER */ +#if _FFR_SS_PER_DAEMON + int d_supersafe; +#endif /* _FFR_SS_PER_DAEMON */ +}; + +typedef struct daemon DAEMON_T; + +EXTERN DAEMON_T Daemons[MAXDAEMONS]; + +#define DPO_NOTSET (-1) /* daemon option (int) not set */ +/* see also sendmail.h: SuperSafe values */ + +extern bool refuseconnections __P((ENVELOPE *, int, bool)); + +#undef EXTERN +#endif /* ! DAEMON_H */ Property changes on: stable/6/contrib/sendmail/src/daemon.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/contrib/sendmail/src/map.h =================================================================== --- stable/6/contrib/sendmail/src/map.h (nonexistent) +++ stable/6/contrib/sendmail/src/map.h (revision 168599) @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2006 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + * + * $Id: map.h,v 8.3 2006/12/19 19:49:51 ca Exp $ + */ + +#ifndef _MAP_H +# define _MAP_H 1 + +extern char *arith_map_lookup __P((MAP *, char *, char **, int *)); + +extern char *bestmx_map_lookup __P((MAP *, char *, char **, int *)); + +extern char *bogus_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool bt_map_open __P((MAP *, int)); + +extern char *db_map_lookup __P((MAP *, char *, char **, int *)); + +extern void db_map_store __P((MAP *, char *, char *)); +extern void db_map_close __P((MAP *)); + +extern bool dequote_init __P((MAP *, char *)); +extern char *dequote_map __P((MAP *, char *, char **, int *)); + +extern bool dns_map_open __P((MAP *, int)); +extern bool dns_map_parseargs __P((MAP *, char *)); +extern char *dns_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool dprintf_map_parseargs __P((MAP *, char *)); +extern char *dprintf_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool hash_map_open __P((MAP *, int)); + +extern bool host_map_init __P((MAP *, char *)); +extern char *host_map_lookup __P((MAP *, char *, char **, int *)); + +extern char *impl_map_lookup __P((MAP *, char *, char **, int *)); +extern void impl_map_store __P((MAP *, char *, char *)); +extern bool impl_map_open __P((MAP *, int)); +extern void impl_map_close __P((MAP *)); + +extern char *macro_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool map_parseargs __P((MAP *, char *)); + +extern bool nis_map_open __P((MAP *, int)); +extern char *nis_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool null_map_open __P((MAP *, int)); +extern void null_map_close __P((MAP *)); +extern char *null_map_lookup __P((MAP *, char *, char **, int *)); +extern void null_map_store __P((MAP *, char *, char *)); + +extern char *prog_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool regex_map_init __P((MAP *, char *)); +extern char *regex_map_lookup __P((MAP *, char *, char **, int *)); + +extern char *seq_map_lookup __P((MAP *, char *, char **, int *)); +extern void seq_map_store __P((MAP *, char *, char *)); +extern bool seq_map_parse __P((MAP *, char *)); + +extern char *stab_map_lookup __P((MAP *, char *, char **, int *)); +extern void stab_map_store __P((MAP *, char *, char *)); +extern bool stab_map_open __P((MAP *, int)); + +extern bool switch_map_open __P((MAP *, int)); + +extern bool syslog_map_parseargs __P((MAP *, char *)); +extern char *syslog_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool text_map_open __P((MAP *, int)); +extern char *text_map_lookup __P((MAP *, char *, char **, int *)); + +extern char *udb_map_lookup __P((MAP *, char *, char **, int *)); + +extern bool user_map_open __P((MAP *, int)); +extern char *user_map_lookup __P((MAP *, char *, char **, int *)); + +#endif /* ! _MAP_H */ Property changes on: stable/6/contrib/sendmail/src/map.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/etc/rc.d/FILESYSTEMS =================================================================== --- stable/6/etc/rc.d/FILESYSTEMS (nonexistent) +++ stable/6/etc/rc.d/FILESYSTEMS (revision 168599) @@ -0,0 +1,12 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: FILESYSTEMS +# REQUIRE: root mountcritlocal zfs + +# This is a dummy dependency, for services which require file systems +# to be mounted before starting. It also serves as the default early / +# late divider; after this point, rc.d directories are rescanned to +# catch scripts from other file systems than /. Property changes on: stable/6/etc/rc.d/FILESYSTEMS ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/share/man/man4/edsc.4 =================================================================== --- stable/6/share/man/man4/edsc.4 (nonexistent) +++ stable/6/share/man/man4/edsc.4 (revision 168599) @@ -0,0 +1,111 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" From: @(#)lo.4 8.1 (Berkeley) 6/5/93 +.\" $FreeBSD$ +.\" +.Dd March 25, 2007 +.Dt EDSC 4 +.Os +.Sh NAME +.Nm edsc +.Nd Ethernet discard network interface +.Sh SYNOPSIS +.Cd "device edsc" +.Sh DESCRIPTION +The +.Nm +interface is a software discard mechanism which may be +used for performance analysis and software testing. +It imitates an Ethernet device, which +allows for its use in conjunction with such drivers as +.Xr if_bridge 4 +and +.Xr vlan 4 . +.Pp +As with other network interfaces, an +.Nm +interface must have network addresses assigned for each address family +with which it is to be used. +These addresses may be set or changed with the +.Dv SIOCSIFADDR +.Xr ioctl 2 +or +.Xr ifconfig 8 +utility. +.Pp +Each +.Nm +interface is created at runtime using interface cloning. +This is most easily done with the +.Xr ifconfig 8 +.Cm create +command or using the +.Va cloned_interfaces +variable in +.Xr rc.conf 5 . +.Sh SEE ALSO +.Xr ioctl 2 , +.Xr arp 4 , +.Xr if_bridge 4 , +.Xr inet 4 , +.Xr intro 4 , +.Xr vlan 4 , +.Xr rc.conf 5 , +.Xr arp 8 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +device was derived from the +.Xr disc 4 +device and first appeared in +.Fx 7.0 . +This manpage was adapted from +.Xr disc 4 . +.Sh CAVEATS +Since outgoing packets are just discarded by +.Nm , +ARP requests stay unreplied. +Consequently, an IP packet cannot be sent via +.Nm +until a static +.Xr arp 4 +entry is created for its next hop using +.Xr arp 8 . +.Pp +Initially an +.Nm +interface has a zero link level address. +It can be changed with +.Xr ifconfig 8 +.Cm lladdr +if needed. Property changes on: stable/6/share/man/man4/edsc.4 ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/sys/cam/scsi/scsi_sg.c =================================================================== --- stable/6/sys/cam/scsi/scsi_sg.c (nonexistent) +++ stable/6/sys/cam/scsi/scsi_sg.c (revision 168599) @@ -0,0 +1,994 @@ +/*- + * Copyright (c) 2007 Scott Long + * 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, + * without modification, immediately at the beginning of the file. + * 2. 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. + */ + +/* + * scsi_sg peripheral driver. This driver is meant to implement the Linux + * SG passthrough interface for SCSI. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +typedef enum { + SG_FLAG_OPEN = 0x01, + SG_FLAG_LOCKED = 0x02, + SG_FLAG_INVALID = 0x04 +} sg_flags; + +typedef enum { + SG_STATE_NORMAL +} sg_state; + +typedef enum { + SG_RDWR_FREE, + SG_RDWR_INPROG, + SG_RDWR_DONE +} sg_rdwr_state; + +typedef enum { + SG_CCB_RDWR_IO, + SG_CCB_WAITING +} sg_ccb_types; + +#define ccb_type ppriv_field0 +#define ccb_rdwr ppriv_ptr1 + +struct sg_rdwr { + TAILQ_ENTRY(sg_rdwr) rdwr_link; + int tag; + int state; + int buf_len; + char *buf; + union ccb *ccb; + union { + struct sg_header hdr; + struct sg_io_hdr io_hdr; + } hdr; +}; + +struct sg_softc { + sg_state state; + sg_flags flags; + struct devstat *device_stats; + TAILQ_HEAD(, sg_rdwr) rdwr_done; + struct cdev *dev; + struct cdev *devalias; + int sg_timeout; + int sg_user_timeout; + uint8_t pd_type; + union ccb saved_ccb; +}; + +static d_open_t sgopen; +static d_close_t sgclose; +static d_ioctl_t sgioctl; +static d_write_t sgwrite; +static d_read_t sgread; + +static periph_init_t sginit; +static periph_ctor_t sgregister; +static periph_oninv_t sgoninvalidate; +static periph_dtor_t sgcleanup; +static periph_start_t sgstart; +static void sgasync(void *callback_arg, uint32_t code, + struct cam_path *path, void *arg); +static void sgdone(struct cam_periph *periph, union ccb *done_ccb); +static int sgsendccb(struct cam_periph *periph, union ccb *ccb); +static int sgsendrdwr(struct cam_periph *periph, union ccb *ccb); +static int sgerror(union ccb *ccb, uint32_t cam_flags, + uint32_t sense_flags); +static void sg_scsiio_status(struct ccb_scsiio *csio, + u_short *hoststat, u_short *drvstat); + +static int scsi_group_len(u_char cmd); + +static struct periph_driver sgdriver = +{ + sginit, "sg", + TAILQ_HEAD_INITIALIZER(sgdriver.units), /* gen */ 0 +}; +PERIPHDRIVER_DECLARE(sg, sgdriver); + +static struct cdevsw sg_cdevsw = { + .d_version = D_VERSION, + .d_flags = D_NEEDGIANT, + .d_open = sgopen, + .d_close = sgclose, + .d_ioctl = sgioctl, + .d_write = sgwrite, + .d_read = sgread, + .d_name = "sg", +}; + +static int sg_version = 30125; + +static void +sginit(void) +{ + cam_status status; + struct cam_path *path; + + /* + * Install a global async callback. This callback will receive aync + * callbacks like "new device found". + */ + status = xpt_create_path(&path, /*periph*/NULL, CAM_XPT_PATH_ID, + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); + + if (status == CAM_REQ_CMP) { + struct ccb_setasync csa; + + xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5); + csa.ccb_h.func_code = XPT_SASYNC_CB; + csa.event_enable = AC_FOUND_DEVICE; + csa.callback = sgasync; + csa.callback_arg = NULL; + xpt_action((union ccb *)&csa); + status = csa.ccb_h.status; + xpt_free_path(path); + } + + if (status != CAM_REQ_CMP) { + printf("sg: Failed to attach master async callbac " + "due to status 0x%x!\n", status); + } +} + +static void +sgoninvalidate(struct cam_periph *periph) +{ + struct sg_softc *softc; + struct ccb_setasync csa; + + softc = (struct sg_softc *)periph->softc; + + /* + * Deregister any async callbacks. + */ + xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5); + csa.ccb_h.func_code = XPT_SASYNC_CB; + csa.event_enable = 0; + csa.callback = sgasync; + csa.callback_arg = periph; + xpt_action((union ccb *)&csa); + + softc->flags |= SG_FLAG_INVALID; + + /* + * XXX Return all queued I/O with ENXIO. + * XXX Handle any transactions queued to the card + * with XPT_ABORT_CCB. + */ + + if (bootverbose) { + xpt_print(periph->path, "lost device\n"); + } +} + +static void +sgcleanup(struct cam_periph *periph) +{ + struct sg_softc *softc; + + softc = (struct sg_softc *)periph->softc; + devstat_remove_entry(softc->device_stats); + destroy_dev(softc->dev); + destroy_dev(softc->devalias); + if (bootverbose) { + xpt_print(periph->path, "removing device entry\n"); + } + free(softc, M_DEVBUF); +} + +static void +sgasync(void *callback_arg, uint32_t code, struct cam_path *path, void *arg) +{ + struct cam_periph *periph; + + periph = (struct cam_periph *)callback_arg; + + switch (code) { + case AC_FOUND_DEVICE: + { + struct ccb_getdev *cgd; + cam_status status; + + cgd = (struct ccb_getdev *)arg; + if (cgd == NULL) + break; + + /* + * Allocate a peripheral instance for this device and + * start the probe process. + */ + status = cam_periph_alloc(sgregister, sgoninvalidate, + sgcleanup, sgstart, "sg", + CAM_PERIPH_BIO, cgd->ccb_h.path, + sgasync, AC_FOUND_DEVICE, cgd); + if ((status != CAM_REQ_CMP) && (status != CAM_REQ_INPROG)) { + const struct cam_status_entry *entry; + + entry = cam_fetch_status_entry(status); + printf("sgasync: Unable to attach new device " + "due to status %#x: %s\n", status, entry ? + entry->status_text : "Unknown"); + } + break; + } + default: + cam_periph_async(periph, code, path, arg); + break; + } +} + +static cam_status +sgregister(struct cam_periph *periph, void *arg) +{ + struct sg_softc *softc; + struct ccb_setasync csa; + struct ccb_getdev *cgd; + int no_tags; + + cgd = (struct ccb_getdev *)arg; + if (periph == NULL) { + printf("sgregister: periph was NULL!!\n"); + return (CAM_REQ_CMP_ERR); + } + + if (cgd == NULL) { + printf("sgregister: no getdev CCB, can't register device\n"); + return (CAM_REQ_CMP_ERR); + } + + softc = malloc(sizeof(*softc), M_DEVBUF, M_ZERO | M_NOWAIT); + if (softc == NULL) { + printf("sgregister: Unable to allocate softc\n"); + return (CAM_REQ_CMP_ERR); + } + + softc->state = SG_STATE_NORMAL; + softc->pd_type = SID_TYPE(&cgd->inq_data); + softc->sg_timeout = SG_DEFAULT_TIMEOUT / SG_DEFAULT_HZ * hz; + softc->sg_user_timeout = SG_DEFAULT_TIMEOUT; + TAILQ_INIT(&softc->rdwr_done); + periph->softc = softc; + + /* + * We pass in 0 for all blocksize, since we don't know what the + * blocksize of the device is, if it even has a blocksize. + */ + no_tags = (cgd->inq_data.flags & SID_CmdQue) == 0; + softc->device_stats = devstat_new_entry("sg", + unit2minor(periph->unit_number), 0, + DEVSTAT_NO_BLOCKSIZE + | (no_tags ? DEVSTAT_NO_ORDERED_TAGS : 0), + softc->pd_type | + DEVSTAT_TYPE_IF_SCSI | + DEVSTAT_TYPE_PASS, + DEVSTAT_PRIORITY_PASS); + + /* Register the device */ + softc->dev = make_dev(&sg_cdevsw, unit2minor(periph->unit_number), + UID_ROOT, GID_OPERATOR, 0600, "%s%d", + periph->periph_name, periph->unit_number); + softc->devalias = make_dev_alias(softc->dev, "sg%c", + 'a' + periph->unit_number); + softc->dev->si_drv1 = periph; + + /* + * Add as async callback so that we get + * notified if this device goes away. + */ + xpt_setup_ccb(&csa.ccb_h, periph->path, /*priority*/5); + csa.ccb_h.func_code = XPT_SASYNC_CB; + csa.event_enable = AC_LOST_DEVICE; + csa.callback = sgasync; + csa.callback_arg = periph; + xpt_action((union ccb *)&csa); + + if (bootverbose) + xpt_announce_periph(periph, NULL); + + return (CAM_REQ_CMP); +} + +static void +sgstart(struct cam_periph *periph, union ccb *start_ccb) +{ + struct sg_softc *softc; + + softc = (struct sg_softc *)periph->softc; + + switch (softc->state) { + case SG_STATE_NORMAL: + start_ccb->ccb_h.ccb_type = SG_CCB_WAITING; + SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h, + periph_links.sle); + periph->immediate_priority = CAM_PRIORITY_NONE; + wakeup(&periph->ccb_list); + break; + } +} + +static void +sgdone(struct cam_periph *periph, union ccb *done_ccb) +{ + struct sg_softc *softc; + struct ccb_scsiio *csio; + + softc = (struct sg_softc *)periph->softc; + csio = &done_ccb->csio; + switch (csio->ccb_h.ccb_type) { + case SG_CCB_WAITING: + /* Caller will release the CCB */ + wakeup(&done_ccb->ccb_h.cbfcnp); + return; + case SG_CCB_RDWR_IO: + { + struct sg_rdwr *rdwr; + int state; + + devstat_end_transaction(softc->device_stats, + csio->dxfer_len, + csio->tag_action & 0xf, + ((csio->ccb_h.flags & CAM_DIR_MASK) == + CAM_DIR_NONE) ? DEVSTAT_NO_DATA : + (csio->ccb_h.flags & CAM_DIR_OUT) ? + DEVSTAT_WRITE : DEVSTAT_READ, + NULL, NULL); + + rdwr = done_ccb->ccb_h.ccb_rdwr; + state = rdwr->state; + rdwr->state = SG_RDWR_DONE; + wakeup(rdwr); + break; + } + default: + panic("unknown sg CCB type"); + } +} + +static int +sgopen(struct cdev *dev, int flags, int fmt, struct thread *td) +{ + struct cam_periph *periph; + struct sg_softc *softc; + int error = 0; + + periph = (struct cam_periph *)dev->si_drv1; + if (periph == NULL) + return (ENXIO); + + softc = (struct sg_softc *)periph->softc; + if (softc->flags & SG_FLAG_INVALID) + return (ENXIO); + + /* + * Don't allow access when we're running at a high securelevel. + */ + error = securelevel_gt(td->td_ucred, 1); + if (error) + return (error); + + if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) + return (error); + + if ((softc->flags & SG_FLAG_OPEN) == 0) { + if (cam_periph_acquire(periph) != CAM_REQ_CMP) + return (ENXIO); + softc->flags |= SG_FLAG_OPEN; + } + + cam_periph_unlock(periph); + + return (error); +} + +static int +sgclose(struct cdev *dev, int flag, int fmt, struct thread *td) +{ + struct cam_periph *periph; + struct sg_softc *softc; + int error; + + periph = (struct cam_periph *)dev->si_drv1; + if (periph == NULL) + return (ENXIO); + + softc = (struct sg_softc *)periph->softc; + + if ((error = cam_periph_lock(periph, PRIBIO)) != 0) + return (error); + + softc->flags &= ~SG_FLAG_OPEN; + + cam_periph_unlock(periph); + cam_periph_release(periph); + + return (0); +} + +static int +sgioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) +{ + union ccb *ccb; + struct ccb_scsiio *csio; + struct cam_periph *periph; + struct sg_softc *softc; + struct sg_io_hdr req; + int dir, error; + + periph = (struct cam_periph *)dev->si_drv1; + if (periph == NULL) + return (ENXIO); + + softc = (struct sg_softc *)periph->softc; + error = 0; + + switch (cmd) { + case LINUX_SCSI_GET_BUS_NUMBER: { + int busno; + + busno = xpt_path_path_id(periph->path); + error = copyout(&busno, arg, sizeof(busno)); + break; + } + case LINUX_SCSI_GET_IDLUN: { + struct scsi_idlun idlun; + struct cam_sim *sim; + + idlun.dev_id = xpt_path_target_id(periph->path); + sim = xpt_path_sim(periph->path); + idlun.host_unique_id = sim->unit_number; + error = copyout(&idlun, arg, sizeof(idlun)); + break; + } + case SG_GET_VERSION_NUM: + case LINUX_SG_GET_VERSION_NUM: + error = copyout(&sg_version, arg, sizeof(sg_version)); + break; + case SG_SET_TIMEOUT: + case LINUX_SG_SET_TIMEOUT: { + u_int user_timeout; + + error = copyin(arg, &user_timeout, sizeof(u_int)); + if (error == 0) { + softc->sg_user_timeout = user_timeout; + softc->sg_timeout = user_timeout / SG_DEFAULT_HZ * hz; + } + break; + } + case SG_GET_TIMEOUT: + case LINUX_SG_GET_TIMEOUT: + /* + * The value is returned directly to the syscall. + */ + td->td_retval[0] = softc->sg_user_timeout; + error = 0; + break; + case SG_IO: + case LINUX_SG_IO: + error = copyin(arg, &req, sizeof(req)); + if (error) + break; + + if (req.cmd_len > IOCDBLEN) { + error = EINVAL; + break; + } + + if (req.iovec_count != 0) { + error = EOPNOTSUPP; + break; + } + + ccb = cam_periph_getccb(periph, /*priority*/5); + csio = &ccb->csio; + + error = copyin(req.cmdp, &csio->cdb_io.cdb_bytes, + req.cmd_len); + if (error) { + xpt_release_ccb(ccb); + break; + } + + switch(req.dxfer_direction) { + case SG_DXFER_TO_DEV: + dir = CAM_DIR_OUT; + break; + case SG_DXFER_FROM_DEV: + dir = CAM_DIR_IN; + break; + case SG_DXFER_TO_FROM_DEV: + dir = CAM_DIR_IN | CAM_DIR_OUT; + break; + case SG_DXFER_NONE: + default: + dir = CAM_DIR_NONE; + break; + } + + cam_fill_csio(csio, + /*retries*/1, + sgdone, + dir|CAM_DEV_QFRZDIS, + MSG_SIMPLE_Q_TAG, + req.dxferp, + req.dxfer_len, + req.mx_sb_len, + req.cmd_len, + req.timeout); + + error = sgsendccb(periph, ccb); + if (error) { + req.host_status = DID_ERROR; + req.driver_status = DRIVER_INVALID; + xpt_release_ccb(ccb); + break; + } + + req.status = csio->scsi_status; + req.masked_status = (csio->scsi_status >> 1) & 0x7f; + sg_scsiio_status(csio, &req.host_status, &req.driver_status); + req.resid = csio->resid; + req.duration = csio->ccb_h.timeout; + req.info = 0; + + error = copyout(&req, arg, sizeof(req)); + if ((error == 0) && (csio->ccb_h.status & CAM_AUTOSNS_VALID) + && (req.sbp != NULL)) { + req.sb_len_wr = req.mx_sb_len - csio->sense_resid; + error = copyout(&csio->sense_data, req.sbp, + req.sb_len_wr); + } + + xpt_release_ccb(ccb); + break; + + case SG_GET_RESERVED_SIZE: + case LINUX_SG_GET_RESERVED_SIZE: { + int size = 32768; + + error = copyout(&size, arg, sizeof(size)); + break; + } + + case SG_GET_SCSI_ID: + case LINUX_SG_GET_SCSI_ID: + { + struct sg_scsi_id id; + + id.host_no = 0; /* XXX */ + id.channel = xpt_path_path_id(periph->path); + id.scsi_id = xpt_path_target_id(periph->path); + id.lun = xpt_path_lun_id(periph->path); + id.scsi_type = softc->pd_type; + id.h_cmd_per_lun = 1; + id.d_queue_depth = 1; + id.unused[0] = 0; + id.unused[1] = 0; + + error = copyout(&id, arg, sizeof(id)); + break; + } + + case SG_EMULATED_HOST: + case SG_SET_TRANSFORM: + case SG_GET_TRANSFORM: + case SG_GET_NUM_WAITING: + case SG_SCSI_RESET: + case SG_GET_REQUEST_TABLE: + case SG_SET_KEEP_ORPHAN: + case SG_GET_KEEP_ORPHAN: + case SG_GET_ACCESS_COUNT: + case SG_SET_FORCE_LOW_DMA: + case SG_GET_LOW_DMA: + case SG_GET_SG_TABLESIZE: + case SG_SET_FORCE_PACK_ID: + case SG_GET_PACK_ID: + case SG_SET_RESERVED_SIZE: + case SG_GET_COMMAND_Q: + case SG_SET_COMMAND_Q: + case SG_SET_DEBUG: + case SG_NEXT_CMD_LEN: + case LINUX_SG_EMULATED_HOST: + case LINUX_SG_SET_TRANSFORM: + case LINUX_SG_GET_TRANSFORM: + case LINUX_SG_GET_NUM_WAITING: + case LINUX_SG_SCSI_RESET: + case LINUX_SG_GET_REQUEST_TABLE: + case LINUX_SG_SET_KEEP_ORPHAN: + case LINUX_SG_GET_KEEP_ORPHAN: + case LINUX_SG_GET_ACCESS_COUNT: + case LINUX_SG_SET_FORCE_LOW_DMA: + case LINUX_SG_GET_LOW_DMA: + case LINUX_SG_GET_SG_TABLESIZE: + case LINUX_SG_SET_FORCE_PACK_ID: + case LINUX_SG_GET_PACK_ID: + case LINUX_SG_SET_RESERVED_SIZE: + case LINUX_SG_GET_COMMAND_Q: + case LINUX_SG_SET_COMMAND_Q: + case LINUX_SG_SET_DEBUG: + case LINUX_SG_NEXT_CMD_LEN: + default: +#ifdef CAMDEBUG + printf("sgioctl: rejecting cmd 0x%lx\n", cmd); +#endif + error = ENODEV; + break; + } + + return (error); +} + +static int +sgwrite(struct cdev *dev, struct uio *uio, int ioflag) +{ + union ccb *ccb; + struct cam_periph *periph; + struct ccb_scsiio *csio; + struct sg_softc *sc; + struct sg_header *hdr; + struct sg_rdwr *rdwr; + u_char cdb_cmd; + char *buf; + int error = 0, cdb_len, buf_len, dir; + + periph = dev->si_drv1; + sc = periph->softc; + rdwr = malloc(sizeof(*rdwr), M_DEVBUF, M_WAITOK | M_ZERO); + hdr = &rdwr->hdr.hdr; + + /* Copy in the header block and sanity check it */ + if (uio->uio_resid < sizeof(*hdr)) { + error = EINVAL; + goto out_hdr; + } + error = uiomove(hdr, sizeof(*hdr), uio); + if (error) + goto out_hdr; + + ccb = xpt_alloc_ccb(); + if (ccb == NULL) { + error = ENOMEM; + goto out_hdr; + } + xpt_setup_ccb(&ccb->ccb_h, periph->path, /*priority*/5); + csio = &ccb->csio; + + /* + * Copy in the CDB block. The designers of the interface didn't + * bother to provide a size for this in the header, so we have to + * figure it out ourselves. + */ + if (uio->uio_resid < 1) + goto out_ccb; + error = uiomove(&cdb_cmd, 1, uio); + if (error) + goto out_ccb; + if (hdr->twelve_byte) + cdb_len = 12; + else + cdb_len = scsi_group_len(cdb_cmd); + /* + * We've already read the first byte of the CDB and advanced the uio + * pointer. Just read the rest. + */ + csio->cdb_io.cdb_bytes[0] = cdb_cmd; + error = uiomove(&csio->cdb_io.cdb_bytes[1], cdb_len - 1, uio); + if (error) + goto out_ccb; + + /* + * Now set up the data block. Again, the designers didn't bother + * to make this reliable. + */ + buf_len = uio->uio_resid; + if (buf_len != 0) { + buf = malloc(buf_len, M_DEVBUF, M_WAITOK | M_ZERO); + error = uiomove(buf, buf_len, uio); + if (error) + goto out_buf; + dir = CAM_DIR_OUT; + } else if (hdr->reply_len != 0) { + buf = malloc(hdr->reply_len, M_DEVBUF, M_WAITOK | M_ZERO); + buf_len = hdr->reply_len; + dir = CAM_DIR_IN; + } else { + buf = NULL; + buf_len = 0; + dir = CAM_DIR_NONE; + } + + cam_fill_csio(csio, + /*retries*/1, + sgdone, + dir|CAM_DEV_QFRZDIS, + MSG_SIMPLE_Q_TAG, + buf, + buf_len, + SG_MAX_SENSE, + cdb_len, + sc->sg_timeout); + + /* + * Send off the command and hope that it works. This path does not + * go through sgstart because the I/O is supposed to be asynchronous. + */ + rdwr->buf = buf; + rdwr->buf_len = buf_len; + rdwr->tag = hdr->pack_id; + rdwr->ccb = ccb; + rdwr->state = SG_RDWR_INPROG; + ccb->ccb_h.ccb_rdwr = rdwr; + ccb->ccb_h.ccb_type = SG_CCB_RDWR_IO; + TAILQ_INSERT_TAIL(&sc->rdwr_done, rdwr, rdwr_link); + return (sgsendrdwr(periph, ccb)); + +out_buf: + free(buf, M_DEVBUF); +out_ccb: + xpt_free_ccb(ccb); +out_hdr: + free(rdwr, M_DEVBUF); + return (error); +} + +static int +sgread(struct cdev *dev, struct uio *uio, int ioflag) +{ + struct ccb_scsiio *csio; + struct cam_periph *periph; + struct sg_softc *sc; + struct sg_header *hdr; + struct sg_rdwr *rdwr; + u_short hstat, dstat; + int error, pack_len, reply_len, pack_id; + + periph = dev->si_drv1; + sc = periph->softc; + + /* XXX The pack len field needs to be updated and written out instead + * of discarded. Not sure how to do that. + */ + uio->uio_rw = UIO_WRITE; + if ((error = uiomove(&pack_len, 4, uio)) != 0) + return (error); + if ((error = uiomove(&reply_len, 4, uio)) != 0) + return (error); + if ((error = uiomove(&pack_id, 4, uio)) != 0) + return (error); + uio->uio_rw = UIO_READ; + +search: + TAILQ_FOREACH(rdwr, &sc->rdwr_done, rdwr_link) { + if (rdwr->tag == pack_id) + break; + } + if ((rdwr == NULL) || (rdwr->state != SG_RDWR_DONE)) { + if (tsleep(rdwr, PCATCH, "sgread", 0) == ERESTART) + return (EAGAIN); + goto search; + } + TAILQ_REMOVE(&sc->rdwr_done, rdwr, rdwr_link); + + hdr = &rdwr->hdr.hdr; + csio = &rdwr->ccb->csio; + sg_scsiio_status(csio, &hstat, &dstat); + hdr->host_status = hstat; + hdr->driver_status = dstat; + hdr->target_status = csio->scsi_status >> 1; + + switch (hstat) { + case DID_OK: + case DID_PASSTHROUGH: + case DID_SOFT_ERROR: + hdr->result = 0; + break; + case DID_NO_CONNECT: + case DID_BUS_BUSY: + case DID_TIME_OUT: + hdr->result = EBUSY; + break; + case DID_BAD_TARGET: + case DID_ABORT: + case DID_PARITY: + case DID_RESET: + case DID_BAD_INTR: + case DID_ERROR: + default: + hdr->result = EIO; + break; + } + + if (dstat == DRIVER_SENSE) { + bcopy(&csio->sense_data, hdr->sense_buffer, + min(csio->sense_len, SG_MAX_SENSE)); +#ifdef CAMDEBUG + scsi_sense_print(csio); +#endif + } + + error = uiomove(&hdr->result, sizeof(*hdr) - + offsetof(struct sg_header, result), uio); + if ((error == 0) && (hdr->result == 0)) + error = uiomove(rdwr->buf, rdwr->buf_len, uio); + + xpt_free_ccb(rdwr->ccb); + free(rdwr->buf, M_DEVBUF); + free(rdwr, M_DEVBUF); + return (error); +} + +static int +sgsendccb(struct cam_periph *periph, union ccb *ccb) +{ + struct sg_softc *softc; + struct cam_periph_map_info mapinfo; + int error, need_unmap = 0; + + softc = periph->softc; + if (((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) + && (ccb->csio.data_ptr != NULL)) { + bzero(&mapinfo, sizeof(mapinfo)); + error = cam_periph_mapmem(ccb, &mapinfo); + if (error) + return (error); + need_unmap = 1; + } + + error = cam_periph_runccb(ccb, + sgerror, + CAM_RETRY_SELTO, + SF_RETRY_UA, + softc->device_stats); + + if (need_unmap) + cam_periph_unmapmem(ccb, &mapinfo); + + return (error); +} + +static int +sgsendrdwr(struct cam_periph *periph, union ccb *ccb) +{ + struct sg_softc *softc; + + softc = periph->softc; + devstat_start_transaction(softc->device_stats, NULL); + xpt_action(ccb); + return (0); +} + +static int +sgerror(union ccb *ccb, uint32_t cam_flags, uint32_t sense_flags) +{ + struct cam_periph *periph; + struct sg_softc *softc; + + periph = xpt_path_periph(ccb->ccb_h.path); + softc = (struct sg_softc *)periph->softc; + + return (cam_periph_error(ccb, cam_flags, sense_flags, + &softc->saved_ccb)); +} + +static void +sg_scsiio_status(struct ccb_scsiio *csio, u_short *hoststat, u_short *drvstat) +{ + int status; + + status = csio->ccb_h.status; + + switch (status & CAM_STATUS_MASK) { + case CAM_REQ_CMP: + *hoststat = DID_OK; + *drvstat = 0; + break; + case CAM_REQ_CMP_ERR: + *hoststat = DID_ERROR; + *drvstat = 0; + break; + case CAM_REQ_ABORTED: + *hoststat = DID_ABORT; + *drvstat = 0; + break; + case CAM_REQ_INVALID: + *hoststat = DID_ERROR; + *drvstat = DRIVER_INVALID; + break; + case CAM_DEV_NOT_THERE: + *hoststat = DID_BAD_TARGET; + *drvstat = 0; + case CAM_SEL_TIMEOUT: + *hoststat = DID_NO_CONNECT; + *drvstat = 0; + break; + case CAM_CMD_TIMEOUT: + *hoststat = DID_TIME_OUT; + *drvstat = 0; + break; + case CAM_SCSI_STATUS_ERROR: + *hoststat = DID_ERROR; + *drvstat = 0; + case CAM_SCSI_BUS_RESET: + *hoststat = DID_RESET; + *drvstat = 0; + break; + case CAM_UNCOR_PARITY: + *hoststat = DID_PARITY; + *drvstat = 0; + break; + case CAM_SCSI_BUSY: + *hoststat = DID_BUS_BUSY; + *drvstat = 0; + default: + *hoststat = DID_ERROR; + *drvstat = DRIVER_ERROR; + } + + if (status & CAM_AUTOSNS_VALID) + *drvstat = DRIVER_SENSE; +} + +static int +scsi_group_len(u_char cmd) +{ + int len[] = {6, 10, 10, 12, 12, 12, 10, 10}; + int group; + + group = (cmd >> 5) & 0x7; + return (len[group]); +} + Property changes on: stable/6/sys/cam/scsi/scsi_sg.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/sys/cam/scsi/scsi_sg.h =================================================================== --- stable/6/sys/cam/scsi/scsi_sg.h (nonexistent) +++ stable/6/sys/cam/scsi/scsi_sg.h (revision 168599) @@ -0,0 +1,144 @@ +/* + * Structures and definitions for SCSI commands to the SG passthrough device. + * + * $FreeBSD$ + */ + +#ifndef _SCSI_SG_H +#define _SCSI_SG_H + +#define SGIOC '"' +#define SG_SET_TIMEOUT _IO(SGIOC, 0x01) +#define SG_GET_TIMEOUT _IO(SGIOC, 0x02) +#define SG_EMULATED_HOST _IO(SGIOC, 0x03) +#define SG_SET_TRANSFORM _IO(SGIOC, 0x04) +#define SG_GET_TRANSFORM _IO(SGIOC, 0x05) +#define SG_GET_COMMAND_Q _IO(SGIOC, 0x70) +#define SG_SET_COMMAND_Q _IO(SGIOC, 0x71) +#define SG_GET_RESERVED_SIZE _IO(SGIOC, 0x72) +#define SG_SET_RESERVED_SIZE _IO(SGIOC, 0x75) +#define SG_GET_SCSI_ID _IO(SGIOC, 0x76) +#define SG_SET_FORCE_LOW_DMA _IO(SGIOC, 0x79) +#define SG_GET_LOW_DMA _IO(SGIOC, 0x7a) +#define SG_SET_FORCE_PACK_ID _IO(SGIOC, 0x7b) +#define SG_GET_PACK_ID _IO(SGIOC, 0x7c) +#define SG_GET_NUM_WAITING _IO(SGIOC, 0x7d) +#define SG_SET_DEBUG _IO(SGIOC, 0x7e) +#define SG_GET_SG_TABLESIZE _IO(SGIOC, 0x7f) +#define SG_GET_VERSION_NUM _IO(SGIOC, 0x82) +#define SG_NEXT_CMD_LEN _IO(SGIOC, 0x83) +#define SG_SCSI_RESET _IO(SGIOC, 0x84) +#define SG_IO _IO(SGIOC, 0x85) +#define SG_GET_REQUEST_TABLE _IO(SGIOC, 0x86) +#define SG_SET_KEEP_ORPHAN _IO(SGIOC, 0x87) +#define SG_GET_KEEP_ORPHAN _IO(SGIOC, 0x88) +#define SG_GET_ACCESS_COUNT _IO(SGIOC, 0x89) + +struct sg_io_hdr { + int interface_id; + int dxfer_direction; + u_char cmd_len; + u_char mx_sb_len; + u_short iovec_count; + u_int dxfer_len; + void *dxferp; + u_char *cmdp; + u_char *sbp; + u_int timeout; + u_int flags; + int pack_id; + void *usr_ptr; + u_char status; + u_char masked_status; + u_char msg_status; + u_char sb_len_wr; + u_short host_status; + u_short driver_status; + int resid; + u_int duration; + u_int info; +}; + +#define SG_DXFER_NONE -1 +#define SG_DXFER_TO_DEV -2 +#define SG_DXFER_FROM_DEV -3 +#define SG_DXFER_TO_FROM_DEV -4 +#define SG_DXFER_UNKNOWN -5 + +#define SG_MAX_SENSE 16 +struct sg_header { + int pack_len; + int reply_len; + int pack_id; + int result; + u_int twelve_byte:1; + u_int target_status:5; + u_int host_status:8; + u_int driver_status:8; + u_int other_flags:10; + u_char sense_buffer[SG_MAX_SENSE]; +}; + +struct sg_scsi_id { + int host_no; + int channel; + int scsi_id; + int lun; + int scsi_type; + short h_cmd_per_lun; + short d_queue_depth; + int unused[2]; +}; + +struct scsi_idlun { + uint32_t dev_id; + uint32_t host_unique_id; +}; + +/* + * Host codes + */ +#define DID_OK 0x00 /* OK */ +#define DID_NO_CONNECT 0x01 /* timeout during connect */ +#define DID_BUS_BUSY 0x02 /* timeout during command */ +#define DID_TIME_OUT 0x03 /* other timeout */ +#define DID_BAD_TARGET 0x04 /* bad target */ +#define DID_ABORT 0x05 /* abort */ +#define DID_PARITY 0x06 /* parity error */ +#define DID_ERROR 0x07 /* internal error */ +#define DID_RESET 0x08 /* reset by somebody */ +#define DID_BAD_INTR 0x09 /* unexpected interrupt */ +#define DID_PASSTHROUGH 0x0a /* passthrough */ +#define DID_SOFT_ERROR 0x0b /* low driver wants retry */ +#define DID_IMM_RETRY 0x0c /* retry without decreasing retrycnt */ + +/* + * Driver codes + */ +#define DRIVER_OK 0x00 +#define DRIVER_BUSY 0x01 +#define DRIVER_SOFT 0x02 +#define DRIVER_MEDIA 0x03 +#define DRIVER_ERROR 0x04 + +#define DRIVER_INVALID 0x05 +#define DRIVER_TIMEOUT 0x06 +#define DRIVER_HARD 0x07 +#define DRIVER_SENSE 0x08 + +#define SUGGEST_RETRY 0x10 +#define SUGGEST_ABORT 0x20 +#define SUGGEST_REMAP 0x30 +#define SUGGEST_DIE 0x40 +#define SUGGEST_SENSE 0x80 +#define SUGGEST_IS_OK 0xff + +#define DRIVER_MASK 0x0f +#define SUGGEST_MASK 0xf0 + +/* Other definitions */ +/* HZ isn't always available, so simulate it */ +#define SG_DEFAULT_HZ 1000 +#define SG_DEFAULT_TIMEOUT (60*SG_DEFAULT_HZ) + +#endif /* !_SCSI_SG_H */ Property changes on: stable/6/sys/cam/scsi/scsi_sg.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/sys/modules/if_edsc/Makefile =================================================================== --- stable/6/sys/modules/if_edsc/Makefile (nonexistent) +++ stable/6/sys/modules/if_edsc/Makefile (revision 168599) @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../net + +KMOD= if_edsc +SRCS= if_edsc.c + +.include Property changes on: stable/6/sys/modules/if_edsc/Makefile ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/sys/net/if_edsc.c =================================================================== --- stable/6/sys/net/if_edsc.c (nonexistent) +++ stable/6/sys/net/if_edsc.c (revision 168599) @@ -0,0 +1,354 @@ +/*- + * Copyright (c) 1982, 1986, 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 edsclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following edsclaimer in the + * documentation and/or other materials provided with the distribution. + * 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 EDSCLAIMED. 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. + * + * From: @(#)if_loop.c 8.1 (Berkeley) 6/10/93 + * $FreeBSD$ + */ + +/* + * Discard interface driver for protocol testing and timing. + * Mimics an Ethernet device so that VLANs can be attached to it etc. + */ + +#include /* types, important constants */ +#include /* SYSINIT for load-time initializations */ +#include /* malloc(9) */ +#include /* module(9) */ +#include /* mbuf(9) */ +#include /* struct ifreq */ +#include /* socket ioctl's */ +/* #include if you need printf(9) or other all-purpose globals */ + +#include /* bpf(9) */ +#include /* Ethernet related constants and types */ +#include /* basic part of ifnet(9) */ +#include /* network interface cloning */ +#include /* IFT_ETHER and friends */ +#include /* kernel-only part of ifnet(9) */ + +/* + * Software configuration of an interface specific to this device type. + */ +struct edsc_softc { + struct ifnet *sc_ifp; /* ptr to generic interface configuration */ + + /* + * A non-null driver can keep various things here, for instance, + * the hardware revision, cached values of write-only registers, etc. + */ +}; + +/* + * Simple cloning methods. + * IFC_SIMPLE_DECLARE() expects precisely these names. + */ +static int edsc_clone_create(struct if_clone *, int, caddr_t); +static void edsc_clone_destroy(struct ifnet *); + +/* + * Interface driver methods. + */ +static void edsc_init(void *dummy); +/* static void edsc_input(struct ifnet *ifp, struct mbuf *m); would be here */ +static int edsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); +static void edsc_start(struct ifnet *ifp); + +/* + * We'll allocate softc instances from this. + */ +static MALLOC_DEFINE(M_EDSC, "edsc", "Ethernet discard interface"); + +/* + * Attach to the interface cloning framework under the name of "edsc". + * The second argument is the number of units to be created from + * the outset. It's also the minimum number of units allowed. + * We don't want any units created as soon as the driver is loaded. + */ +IFC_SIMPLE_DECLARE(edsc, 0); + +/* + * Create an interface instance. + */ +static int +edsc_clone_create(struct if_clone *ifc, int unit, caddr_t params) +{ + struct edsc_softc *sc; + struct ifnet *ifp; + static u_char eaddr[ETHER_ADDR_LEN]; /* 0:0:0:0:0:0 */ + + /* + * Allocate soft and ifnet structures. Link each to the other. + */ + sc = malloc(sizeof(struct edsc_softc), M_EDSC, M_WAITOK | M_ZERO); + ifp = sc->sc_ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) { + free(sc, M_EDSC); + return (ENOSPC); + } + + ifp->if_softc = sc; + + /* + * Get a name for this particular interface in its ifnet structure. + */ + if_initname(ifp, ifc->ifc_name, unit); + + /* + * Typical Ethernet interface flags: we can do broadcast and + * multicast but can't hear our own broadcasts or multicasts. + */ + ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX; + + /* + * We can pretent we have the whole set of hardware features + * because we just discard all packets we get from the upper layer. + * However, the features are disabled initially. They can be + * enabled via edsc_ioctl() when needed. + */ + ifp->if_capabilities = + IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWCSUM | + IFCAP_HWCSUM | IFCAP_TSO | + IFCAP_JUMBO_MTU; + ifp->if_capenable = 0; + + /* + * Set the interface driver methods. + */ + ifp->if_init = edsc_init; + /* ifp->if_input = edsc_input; */ + ifp->if_ioctl = edsc_ioctl; + ifp->if_start = edsc_start; + + /* + * Set the maximum output queue length from the global parameter. + */ + ifp->if_snd.ifq_maxlen = ifqmaxlen; + + /* + * Do ifnet initializations common to all Ethernet drivers + * and attach to the network interface framework. + * TODO: Pick a non-zero link level address. + */ + ether_ifattach(ifp, eaddr); + + /* + * Now we can mark the interface as running, i.e., ready + * for operation. + */ + ifp->if_drv_flags |= IFF_DRV_RUNNING; + + return (0); +} + +/* + * Destroy an interface instance. + */ +static void +edsc_clone_destroy(struct ifnet *ifp) +{ + struct edsc_softc *sc = ifp->if_softc; + + /* + * Detach from the network interface framework. + */ + ether_ifdetach(ifp); + + /* + * Free memory occupied by ifnet and softc. + */ + if_free(ifp); + free(sc, M_EDSC); +} + +/* + * This method is invoked from ether_ioctl() when it's time + * to bring up the hardware. + */ +static void +edsc_init(void *dummy) +{ +#if 0 /* what a hardware driver would do here... */ + struct edsc_soft *sc = (struct edsc_softc *)dummy; + struct ifnet *ifp = sc->sc_ifp; + + /* blah-blah-blah */ +#endif +} + +/* + * Network interfaces are controlled via the ioctl(2) syscall. + */ +static int +edsc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + struct ifreq *ifr = (struct ifreq *)data; + + switch (cmd) { + case SIOCSIFCAP: +#if 1 + /* + * Just turn on any capabilities requested. + * The generic ifioctl() function has already made sure + * that they are supported, i.e., set in if_capabilities. + */ + ifp->if_capenable = ifr->ifr_reqcap; +#else + /* + * A h/w driver would need to analyze the requested + * bits and program the hardware, e.g.: + */ + mask = ifp->if_capenable ^ ifr->ifr_reqcap; + + if (mask & IFCAP_VLAN_HWTAGGING) { + ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + + if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) + /* blah-blah-blah */ + else + /* etc-etc-etc */ + } +#endif + break; + + default: + /* + * Offload the rest onto the common Ethernet handler. + */ + return (ether_ioctl(ifp, cmd, data)); + } + + return (0); +} + +/* + * Process the output queue. + */ +static void +edsc_start(struct ifnet *ifp) +{ + struct mbuf *m; + + /* + * A hardware interface driver can set IFF_DRV_OACTIVE + * in ifp->if_drv_flags: + * + * ifp->if_drv_flags |= IFF_DRV_OACTIVE; + * + * to prevent if_start from being invoked again while the + * transmission is under way. The flag is to protect the + * device's transmitter, not the method itself. The output + * queue is locked and several threads can process it in + * parallel safely, so the driver can use other means to + * serialize access to the transmitter. + * + * If using IFF_DRV_OACTIVE, the driver should clear the flag + * not earlier than the current transmission is complete, e.g., + * upon an interrupt from the device, not just before returning + * from if_start. This method merely starts the transmission, + * which may proceed asynchronously. + */ + + /* + * We loop getting packets from the queue until it's empty. + * A h/w driver would loop until the device can accept more + * data into its buffer, or while there are free transmit + * descriptors, or whatever. + */ + for (;;) { + /* + * Try to dequeue one packet. Stop if the queue is empty. + * Use IF_DEQUEUE() here if ALTQ(9) support is unneeded. + */ + IFQ_DEQUEUE(&ifp->if_snd, m); + if (m == NULL) + break; + + /* + * Let bpf(9) at the packet. + */ + BPF_MTAP(ifp, m); + + /* + * Update the interface counters. + */ + ifp->if_obytes += m->m_pkthdr.len; + ifp->if_opackets++; + + /* + * Finally, just drop the packet. + * TODO: Reply to ARP requests unless IFF_NOARP is set. + */ + m_freem(m); + } + + /* + * ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + * would be here only if the transmission were synchronous. + */ +} + +/* + * This function provides handlers for module events, namely load and unload. + */ +static int +edsc_modevent(module_t mod, int type, void *data) +{ + + switch (type) { + case MOD_LOAD: + /* + * Connect to the network interface cloning framework. + */ + if_clone_attach(&edsc_cloner); + break; + + case MOD_UNLOAD: + /* + * Disconnect from the cloning framework. + * Existing interfaces will be disposed of properly. + */ + if_clone_detach(&edsc_cloner); + break; + + default: + /* + * There are other event types, but we don't handle them. + * See module(9). + */ + return (EOPNOTSUPP); + } + return (0); +} + +static moduledata_t edsc_mod = { + "if_edsc", /* name */ + edsc_modevent, /* event handler */ + NULL /* additional data */ +}; + +DECLARE_MODULE(if_edsc, edsc_mod, SI_SUB_PSEUDO, SI_ORDER_ANY); Property changes on: stable/6/sys/net/if_edsc.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/sys/sys/_sx.h =================================================================== --- stable/6/sys/sys/_sx.h (nonexistent) +++ stable/6/sys/sys/_sx.h (revision 168599) @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2007 Attilio Rao + * 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(s), this list of conditions and the following disclaimer as + * the first lines of this file unmodified other than the possible + * addition of one or more copyright notices. + * 2. Redistributions in binary form must reproduce the above copyright + * notice(s), 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 COPYRIGHT HOLDER(S) ``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 COPYRIGHT HOLDER(S) 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS__SX_H_ +#define _SYS__SX_H_ + +/* + * Shared/exclusive lock main structure definition. + */ +struct sx { + struct lock_object lock_object; + volatile uintptr_t sx_lock; + volatile unsigned sx_recurse; +}; + +#endif /* !_SYS__SX_H_ */ Property changes on: stable/6/sys/sys/_sx.h ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/tools/regression/usr.bin/sed/regress.b2a.out =================================================================== --- stable/6/tools/regression/usr.bin/sed/regress.b2a.out (nonexistent) +++ stable/6/tools/regression/usr.bin/sed/regress.b2a.out (revision 168599) @@ -0,0 +1,3 @@ +data +for validation +of sed(1) Property changes on: stable/6/tools/regression/usr.bin/sed/regress.b2a.out ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/tools/regression/usr.bin/sed/regress.c0.out =================================================================== --- stable/6/tools/regression/usr.bin/sed/regress.c0.out (nonexistent) +++ stable/6/tools/regression/usr.bin/sed/regress.c0.out (revision 168599) @@ -0,0 +1,4 @@ +foo +foo +foo +foo Property changes on: stable/6/tools/regression/usr.bin/sed/regress.c0.out ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/tools/regression/usr.bin/sed/regress.c1.out =================================================================== --- stable/6/tools/regression/usr.bin/sed/regress.c1.out (nonexistent) +++ stable/6/tools/regression/usr.bin/sed/regress.c1.out (revision 168599) @@ -0,0 +1,4 @@ +input +data +for validation +foo Property changes on: stable/6/tools/regression/usr.bin/sed/regress.c1.out ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/tools/regression/usr.bin/sed/regress.c2.out =================================================================== --- stable/6/tools/regression/usr.bin/sed/regress.c2.out (nonexistent) +++ stable/6/tools/regression/usr.bin/sed/regress.c2.out (revision 168599) @@ -0,0 +1,3 @@ +input +data +foo Property changes on: stable/6/tools/regression/usr.bin/sed/regress.c2.out ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: stable/6/tools/regression/usr.bin/sed/regress.c3.out =================================================================== --- stable/6/tools/regression/usr.bin/sed/regress.c3.out (nonexistent) +++ stable/6/tools/regression/usr.bin/sed/regress.c3.out (revision 168599) @@ -0,0 +1,3 @@ +input +data +foo Property changes on: stable/6/tools/regression/usr.bin/sed/regress.c3.out ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property