#  -*- text -*-
#
#
#  $Id: 0f045d34f1360a38c0927dbb3e67d572901b7c04 $

#######################################################################
#
#  = Linelog Module
#
#  The `linelog` module will log entries from attributes, string expansions,
#  or static strings, and writes them to a variety of backends, including syslog,
#  flat files, and raw UDP/TCP sockets.
#
#  NOTE: Multiple linelog's modules may be used for any given request.
#  The `logtee` modules will not affect normal logging output.
#  i.e. This logging is *in addition* to any other logging that is
#  done by the server.
#

#
#  ## Configuration Settings
#
linelog {
	#
	#  delimiter::  Custom line delimiters.
	#
	#  Defaults to `\n` (newline) but may be any UTF8 multi-character
	#  string.
	#
#	delimiter = "\n"

	#
	#  format:: The default format string. May be an attribute reference.
	#
	#  e.g. `&User-Name`, or `xlat`, `literal` or `exec`.
	#
	format = "This is a log message for %{User-Name}"

	#
	#  [NOTE]
	#  ====
	#  The `reference` configuration item can be omitted.  If it
	#  is omitted, then the log message is static, and is always
	#  given by `format`, above.
	#
	#  If `reference` is defined, then the value is dynamically
	#  expanded, and the result is used to find another
	#  configuration entry here, with the given name.  That name
	#  is then used as the format string.
	#
	#  If the configuration entry cannot be found, then no log
	#  message is printed.
	#
	#  i.e: You can have many log messages in one `linelog` module.
	#  If this two-step expansion did not exist, you would have
	#  needed to configure one `linelog` module for each log message.
	#  ====
	#

	#
	#  reference::
	#
	#  Reference the `Packet-Type` (`Access-Request`, etc.)  If
	#  `reference` is commented out, the `format` entry above is
	#  used instead.
	#
	#  May be an attribute reference, e.g. `&User-Name`, or `xlat`, `literal` or `exec`.
	#
	reference = "messages.%{&reply.Packet-Type || 'default'}"

	#
	#  messages { ... }::
	#
	#  The messages defined here are chosen from the `reference`
	#  expansion, above.
	#
	#  Pairs may be attributes attribute reference `&User-Name` , `xlat`, `literal` or `exec`.
	#
	messages {
		default = "Unknown packet type %{Packet-Type}"

		Access-Accept = "Sent accept: %{User-Name}"
		Access-Reject = "Sent reject: %{User-Name}"
		Access-Challenge = "Sent challenge: %{User-Name}"
	}

	#
	#  header:: Optional header line format for file output
	#
	#  If the destination is "file" and header is set, then this
	#  is expanded and output as the first line when a new file
	#  is created.
	#
#	header = ""

	#
	#  destination:: What should be done with log messages.
	#
	#  May be one of:
	#
	#  [options="header,autowidth"]
	#  |===
	#  | Option  | Description
	#  | file    | Write to a file.
	#  | request | Write to the logging destination of the current request
	#  | stdout  | Write to stdout
	#  | stderr  | Write to stderr
	#  | syslog  | Send via the system's syslog() function.
	#  | tcp     | Write to a TCP socket.
	#  | udp     | Write to a UDP socket.
	#  | unix    | Write to a UNIX socket.
	#  |===
	#
	#  The `stdout` and `stderr` destinations are likely to work only when
	#  the server is running in debug mode.  When the server is running in
	#  background mode, both `stdout` and `stderr` are usually redirected
	#  to `/dev/null`.
	#
	destination = file

	#
	#  .File as the destination for log messages.
	#
	file {
		#
		#  filename:: The file where the logs will go.
		#
		#  WARNING: We STRONGLY suggest that you do not use
		#  data from the packet as part of the filename.  This
		#  data is untrusted, and may play games with your
		#  file system!  If it is necessary you must set
		#  `escape_filenames = yes` in order to prevent
		#  security issues.
		#
		filename = ${logdir}/linelog

		#
		#  permissions:: The Unix-style permissions on the log file.
		#
		#  Depending on format string, the log file may contain secret or
		#  private information about users.  Keep the file permissions as
		#  restrictive as possible.
		#
		permissions = 0600

		#
		#  group:: The Unix group which owns the log file.
		#
		#  The user that freeradius runs as must be in the specified
		#  group, otherwise it will not be possible to set the group.
		#
#		group = ${security.group}

		#
		#  escape_filenames::
		#
		#  Most file systems can handle nearly the full range
		#  of UTF-8 characters.  Ones that can only deal with
		#  a limited range should set this to `yes`.
		#
		escape_filenames = no

		#
		#  fsync::
		#
		#  Synchronise data written with the file system after every
		#  write, returning fail when the operation fails.
		#
		fsync = no
	}

	#
	#  The connection pool for TCP and Unix socket connections.
	#
	pool {
		#
		#  start:: Connections to create during module instantiation.
		#
		#  If the server cannot create specified number of
		#  connections during instantiation it will exit.
		#  Set to `0` to allow the server to start without the
		#  external service being available.
		#
		start = 0

		#
		#  min:: Minimum number of connections to keep open.
		#
		min = 0

		#
		#  max:: Maximum number of connections.
		#
		#  If these connections are all in use and a new one
		#  is requested, the request will NOT get a connection.
		#
		#  Setting `max` to *LESS* than the number of threads means
		#  that some threads may starve, and you will see errors
		#  like _No connections available and at max connection limit_.
		#
		#  Setting `max` to MORE than the number of threads means
		#  that there are more connections than necessary.
		#
		#  If `max` is not specified, then it defaults to the number
		#  of workers configured.
		#
#		max =

		#
		#  spare:: Spare connections to be left idle.
		#
		#  NOTE: Idle connections WILL be closed if `idle_timeout`
		#  is set.  This should be less than or equal to `max` above.
		#
		spare = 1

		#
		#  uses:: Number of uses before the connection is closed.
		#
		#  `0` means "infinite"
		#
		uses = 0

		#
		#  retry_delay::
		#
		#  The number of seconds to wait after the server tries
		#  to open a connection, and fails.  During this time,
		#  no new connections will be opened.
		#
		retry_delay = 30

		#
		#  lifetime:: The lifetime (in seconds) of the connection.
		#
		lifetime = 0

		#
		#  idle_timeout:: A connection which is unused for this length
		#  of time will be closed.
		#
		#  Default `60` seconds.
		#
		idle_timeout = 60

		#
		#  NOTE: All configuration settings are enforced.  If a
		#  connection is closed because of `idle_timeout`,
		#  `uses`, or `lifetime`, then the total number of
		#  connections MAY fall below `min`.  When that
		#  happens, it will open a new connection.  It will
		#  also log a WARNING message.
		#
		#  The solution is to either lower the `min` connections,
		#  or increase `lifetime`/`idle_timeout`.
		#
	}

	#
	#  .UNIX socket-file as destination
	#
#	unix {
		#
		#  filename:: Full path to the `unix socket` file.
		#
#		filename = /path/to/unix.socket

		#
		#  pool:: The `pool { ... }` of connections.
		#
#		pool = ${..pool}
#	}

	#
	#  .TCP-server as a destination
	#
	tcp {
		#
		#  server:: Server to connect to.
		#
		server = "localhost"

		#
		#  port:: Port to connect to.
		#
		port = 514

		#
		#  timeout:: Connect and write timeout (in seconds).
		#
		timeout = 2.0

		#
		#  pool:: The `pool { ... }` of connections.
		#
#		pool = ${..pool}
	}

	#
	#  .UDP-server as a destination
	#
	udp {
		#
		#  server:: Server to connect to.
		#
		server = "localhost"

		#
		#  port:: Port to connect to.
		#
		port = 514

		#
		#  timeout:: Connect and write timeout (in seconds).
		#
		timeout = 2.0

		#
		#  pool:: The `pool { ... }` of connections.
		#
		pool = ${..pool}
	}

	#
	#  .Syslog-server as a destination
	#
	syslog {
		#
		#  facility:: Syslog facility (if logging via syslog).
		#
		#  Defaults to the syslog_facility config item in radiusd.conf.
		#
		#  Standard facilities are:
		#
		#  [options="header,autowidth"]
		#  |===
		#  | Option     | Description
		#  | kern       | Messages generated by the kernel.  These cannot
		#                 be generated by any user processes.
		#  | user       | Messages generated by random user processes.
		#                 This is the default facility identifier if
		#                 none is specified.
		#  | mail       | The mail system.
		#  | daemon     | System daemons, such as routed(8), that are not
		#                 provided for explicitly by other facilities.
		#  | auth       | The authorization system: login(1), su(1),
		#                 getty(8), etc.
		#  | lpr        | The line printer spooling system: cups-lpd(8),
		#                 cupsd(8), etc.
		#  | news       | The network news system.
		#  | uucp       | The uucp system.
		#  | cron       | The cron daemon: cron(8).
		#  | authpriv   | The same as LOG_AUTH, but logged to a file
		#                 readable only by selected individuals.
		#  | ftp        | The file transfer protocol daemons: ftpd(8),
		#                 tftpd(8).
		#  | local[0-7] | Reserved for local use.
		#  |===
		#
		#  Default is `daemon`.
		#
#		facility = daemon

		#
		#  severity:: Syslog severity (if logging via `syslog`).
		#
		#  Possible values are:
		#
		#  [options="header,autowidth"]
		#  |===
		#  | Option     | Description
		#  | emergency  | A panic condition.  This is normally broadcast
		#                 to all users.
		#  | alert      | A condition that should be corrected immediately,
		#                 such as a corrupted system database.
		#  | critical   | Critical conditions, e.g., hard device errors.
		#  | error      | Errors.
		#  | warning    | Warning messages.
		#  | notice     | Conditions that are not error conditions, but
		#                 should possibly be handled specially.
		#  | info       | Informational messages.
		#  | debug      | Messages that contain information normally of use
		#                 only when debugging a program.
		#  |===
		#
		#  Defaults is `info`.
		#
#		severity = info
	}
}

#
#  ## Sample
#
#  Another example, for accounting packets.
#
linelog log_accounting {
	#
	#  Please see the `linelog` module for common configuration explanation.
	#
	destination = file

	format = ""

	file {
		filename = ${logdir}/linelog-accounting
		permissions = 0600
	}

	reference = "Accounting-Request.%{&Acct-Status-Type || 'unknown'}"

	#
	#  Example for `Accounting-Request`.
	#
	Accounting-Request {
		Start = "Connect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address})"
		Stop = "Disconnect: [%{User-Name}] (did %{Called-Station-Id} cli %{Calling-Station-Id} port %{NAS-Port} ip %{Framed-IP-Address}) %{Acct-Session-Time} seconds"

		#  Don't log anything for these packets.
		Interim-Update = ""

		Accounting-On = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) just came online"
		Accounting-Off = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) just went offline"

		#  Don't log anything for other `Acct-Status-Type` 's.
		unknown = "NAS %{Net.Src.IP} (%{&NAS-IP-Address || &NAS-IPv6-Address}) sent unknown Acct-Status-Type %{Acct-Status-Type}"
	}
}

#
#  ## Authentication success / failure logging
#
#  A set of sample module instances which can replace the previous builtin auth log messages
#
#  The destination settings here pick up from the main radiusd.conf values, but can be
#  amended if these logs need to be sent to a different destination.
#
linelog log_auth_access_accept {
	destination = ${log.destination}
	file {
		filename = ${log.file}
	}
	syslog {
		facility = ${log.syslog_facility}
		severity = notice
	}

	format = "Login OK: [%{User-Name}] (from %client(shortname) port %{NAS-Port} cli %{Calling-Station-Id})"
}

linelog log_auth_access_reject {
	destination = ${log.destination}
	file {
		filename = ${log.file}
	}
	syslog {
		facility = ${log.syslog_facility}
		severity = notice
	}

	format = "Login incorrect (%{Module-Failure-Message}): [%{User-Name}] (from %client(shortname) port %{NAS-Port} cli %{Calling-Station-Id})"
}

linelog log_auth_authentication_pass {
	destination = ${log.destination}
	file {
		filename = ${log.file}
	}
	syslog {
		facility = ${log.syslog_facility}
		severity = notice
	}

	format = "Login OK: [%{User-Name}] (from client %client(shortname))"
}


linelog log_auth_authentication_fail {
	destination = ${log.destination}
	file {
		filename = ${log.file}
	}
	syslog {
		facility = ${log.syslog_facility}
		severity = notice
	}

	format = "Login incorrect (%{Module-Failure-Message}): [%{User-Name}] (from %client(shortname))"
}
