#  -*- text -*-
#
#
#  $Id: faab86542ddf5ebc5e51571c14564c27cd890578 $

#######################################################################
#
#  = 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:: 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:: Whether filenames are escaped.
		#
		#  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:: Forcible sync the data to disk.
		#
		#  Synchronise data written with the file system after every write,
		#  returning fail when the operation fails.
		#
		fsync = no

		#
		#  buffer_count:: How many lines to buffer before writing to disk.
		#
		#  If buffer_count is set, then the module will buffer logs in
		#  memory before writing them to disk.
		#
		#  Setting this to zero will turn off buffering.
		#
		buffer_count = 0;

		#
		#  buffer_delay:: Time delay before writing logs to disk.
		#
		#  If logs are buffered, then they buffered data is written to disk
		#  when either the buffer_count is reached, or when buffer_delay is
		#  reached. The combination of the two settings allows much higher
		#  performance, while still ensuring that logs are regularly written
		#  to disk.
		#
		buffer_delay = 1s
	}

	#
	#  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:: 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:: 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:: 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:: 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))"
}
