noble (5) gensio.5.gz

Provided by: gensio-bin_2.8.2-6.1build1_amd64 bug

NAME

       gensio - How to specify a gensio

SYNOPSIS

       <type>[(options)][,gensio|terminaloptions]

DESCRIPTION

       gensio  stands  for GENeral Stream Input Output.  It provides an abstraction for all kinds of stream I/O,
       and even makes some packet I/O look like stream I/O (like UDP).  In particular, gensio makes it  easy  to
       create encrypted and authenticated connections.

       The  gensio  library  specifies  a  connection (gensio) using a string format.  This consists of a gensio
       type, optional options in parenthesis.  For a terminal gensio (one that is at the bottom of  the  stack),
       it  may take more options separated by a comma.  For filter gensios (ones not on the bottom of the stack)
       another gensio must be specified after the comma.  For instance:

              serialdev,/dev/ttyS0

       specifies a serial port gensio.  Or:

              tcp(readbuf=100),localhost,4000

       specifies a TCP connection with a 100 byte read buffer, to connect to port 4000 on localhost.  Or:

              telnet,tcp,localhost,4000

       specifies a telnet filter on top of a TCP connection.

       When specifying a gensio, you can add quotes (single or double) to remove the special  meaning  for  some
       characters,  so  you  can  have  commas  in  options and such.  They may also be escaped with a "\".  For
       instance, if you are specifying a laddr in an sctp address, you need to do this.  The following address:

              sctp(laddr=localhost,4001),localhost,3023

       will result in a failure because the option splitting code will split at the commas.  Instead, do:

              sctp(laddr="localhost,4001"),localhost,3023

       and it will work.

       Accepter gensios, gensios used for accepting connections, as opposed to connecting gensios, are specified
       in  the  same  way.   Each  individual  type can vary, and some gensios are only connecting gensios.  The
       options can vary from the accepter and connecting gensios of the same type.  For instance,  an  accepting
       TCP gensio does not have to have a hostname, but a connecting one does.

       When an accepter gensio receives a connection, it will create an accepted gensio.  This works mostly like
       a connecting gensio, except some functions may be limited.  You may not be able to close and then open an
       accepted gensio.

       The  gensio  library  has  a concept of client and server.  The accepted gensios are generally considered
       servers.  Connecting gensios are generally considered  clients.   Some  gensios  may  allow  this  to  be
       overridden.

       A gensio may be reliable or not.  A reliable gensio will reliably deliver all data in sequence, like TCP.
       An gensio that is not reliable may drop data or deliver data out of sequence,  like  UDP.   This  can  be
       queried with gensio_is_reliable().

       A  gensio may be packet or not.  A packet gensio will exactly match up writes and reads.  So if you write
       15 bytes into one side, a 15 byte read for that data will appear on the other side.  A gensio that is not
       packet  will  not  respect write boundaries, that 15 byte write may result in multiple reads or it may be
       combined with another write into more than 15 bytes.  Packet I/O requires careful use  to  make  it  work
       correctly.   If  the gensio doesn't have room for another packet, a write will succeed but write 0 bytes.
       Otherwise if you write larger than a packet size, it will only take the number of bytes that can fit into
       a  packet, so it will truncate.  This is useful if you want to stream over a packet interface, but if you
       really want packets you have to make sure all the sizes are set properly. Particularly, you must set  the
       max  read  and write size to the same value.  You should check on writes that it wrote all the data.  You
       can do partial read handling, if you like, but you will only get the rest of the packet on the second and
       following read.

       A  gensio  may be message oriented.  This implementation is stolen from SCTP (even though it's not really
       supported on Linux at the moment).  It basically means you can explicitly mark  message  boundaries  when
       sending  data,  and  that  explicit  mark  will  be set on the read side.  You do this by adding an "eom"
       auxdata on the write; the end of that write it assumed to be the end of a message.  If the write does not
       accept  all  the data, the "eom" is ignored, you must write the remaining data again with "eom" set.  You
       may also do partial write of messages and set "eom" at the end.  On the receive side, "eom" will  be  set
       when the end of a message is delivered.  The data delivered in the receive callback will be only the data
       for that message.  If the user does not accept all the data, the  data  left  in  the  message  is  again
       presented to the user with "eom" set.

       The  options  vary greatly between the different gensios.  Each gensio type will be covered in a separate
       section.  Also note that gensio types can be dynamically added by the  user,  so  there  may  be  gensios
       available that are not described here.

       Unless otherwise noted, every gensio takes a:

       readbuf=<n>
              option to specify the read buffer size.

DEFAULTS

       Every  option  to  a  gensio  (including  the serialdev and ipmisol options), unless othersize stated, is
       available as a default for the gensios.  You can use gensio_set_default() to set the default  value  used
       by  all  gensios  allocated after that point.  If you leave the class NULL, it will set the base default,
       which will affect all gensios unless they have an override.  If you set the class, it  will  only  affect
       gensios with that class name.

       Be very careful with some defaults.  Setting "mode" default, for instance, could really screw things up.

       For string defaults, setting the default value to NULL causes the gensio to use it's backup default.

Serial gensios

       Some  gensio types support serial port setting options.  Standard serial ports, IPMI Serial Over LAN, and
       telnet with RFC2217 enabled.

       A client serial gensio can set and get serial port options using the sergensio_xxx()  functions.   Server
       serial gensios receive requests from the client via GENSIO_EVENT_SER_xxx events in the callback.

Streams and Channels

       Some gensios support the concept of a stream and/or a channel.

       A  stream  is  delivered  as  part  of  the normal data stream of a gensio.  The "default" stream will be
       treated normally.  All other streams will have "stream=<x>" given in the auxdata to specify which  stream
       to write on or which stream was read from.  Streams cannot be individually flow controlled.

       A  channel  is a flow of data like a stream, but it can be individually flow controlled.  It appears as a
       new   gensio   in   the   GENSIO_EVENT_NEW_CHANNEL   callback.    You   can   create   a   channel   with
       gensio_alloc_channel()  and  then  open  it with gensio_open().  Once open, a channel works like a normal
       gensio.  If you close the main channel for a gensio, the other channels will stay open; the resources for
       the main channel will still be kept around until all channels are closed.

       See the indvidual gensio description for more information on streams and channels.

PUBLIC KEY CRYPTOGRAPHY

       The  ssl  and  certauth gensios use public key cryptography.  This section gives a little overview of how
       that works.  You can safely skip this section if you already understand these concepts.

       Public key cryptography is used to authenticate and encrypt information at the beginning  of  a  session.
       It is a fairly expensive operation and is not generally used to encrypt information after the beginning.

       In  public  key  cryptography, you have three basic things: A private key, a certificate (or public key),
       and a certificate authority (CA).

       The private key is just that: private.  You don't even send your private key to a  certificate  authority
       for  signing  of  your  certificate.   Keep it private, non-readable by everyone else.  Protect it, if it
       becomes known your certificate becomes useless to you, anyone can impersonate you.

       The certificate is the public key, and is mathematically associated with a single private key.  It's just
       that,  public,  anyone  can use it to test that you have the private key by asking you to sign some data.
       The data in the certificate (like the Common Name) is part of the certificate.  If that data is modified,
       the certificate validation will fail.

       The  CA is generally a trusted third-party that validates you and signs your certificate (generally for a
       fee).  CAs issue their own public certificates that  are  well-known  and  generally  available  on  your
       system.  The CA certificates are used to prove that your certificate is valid.

   SIGNING
       The  process  if  signing has been mentioned already, but not described.  Basically, you use your private
       key to generate a value over some given data that proves you have the private key.   The  certificate  is
       ised to mathematically verify the signature.

       Two things are normally done with this:

       In  a  public  key  exchange,  the  entity wishing to be authorized sends a certificate.  The authorizing
       entity will look through it's CA for a  certificate  that  has  signed  the  sent  certificate.   If  the
       authorizing  entity  finds  a  certificate  that  can  be used to validate the sent certificate, the sent
       certificate is valid.

       After that, the authorizing entity sends some generally random data  to  the  other  entity.   The  other
       entity  will  take that data, perhaps some other important data that it want to make sure is not modified
       in the transfer, and signs that data.  It sends the  signature  back  to  the  authorizing  entity.   The
       authorizing  entity  can  then use the data and the signature to validate that the sending entity has the
       private key associated with the certificate.

       This is basically how https works.  Note it is the web client that authenticates the web server, not  the
       other  way around.  This proves that you are connecting to the entity you say you are connecting to.  The
       authentication of a web client to the web server is generally done  via  a  different  mechanism  (though
       SSL/TLS used by the ssl gensio has a way to do it, it is not generally used for that purpose).

       In  the  web server scenario, data in the certificate (specifically the Common Name and Subject Alternate
       Name) must match the name of the web page to which you are connecting.  The ssl and certauth  gensios  do
       not do this authentication, that is up to the user if it is necessary.

   ENCRYPTING
       The  certificate  can  be  used  to  encrypt  data that can only be decrypted with the private key.  When
       establishing an encrypted connection, this is generally used to transfer  a  symmetric  cryptography  key
       from  one  entity  to  another  (the authorizing entity to the requesting entity in the case above).  You
       could encrypt all the data with the public key, but that is very expensive and in our example above would
       require certificates and private keys on both ends.

   SELF-SIGNED CERTIFICATES
       It  is  possible  to create a certificate that can act as its own certificate authority.  This is how ssh
       works.  You create a public and private  key.   You  put  the  public  key  in  the  .ssh/authorized_keys
       directory  on  systems where you want to log in.  The certificate acts as both the public key (as part of
       the initial transfer) and the CA (in the authorized_key directory) for authorizing you use of the  system
       you are logging in to.

       ssh  also  stores  places  it  has  connected  to  in  .ssh/known_hosts,  which is the CA in the opposite
       direction.  This is why it asks you if you have never connected to a system before, it doesn't  have  the
       key  in  its  CA.   Or  why, if you connect to a system you have connected to before and the certificates
       don't match or fail validation, it complains about it.

       So if you are using self-signed certificates, you need to be careful to put only ones you  trust  in  the
       CA.   This  is  obviously  not  possible  in a large system like the world wide web, thus the creation of
       third-party trusted CAs.

   TRUST AND CRYPTOGRAPHY
       The above discussions mention trust several times.  Cryptography does not remove the need for trust.   It
       just  makes  trust more convenient.  If someone sends you a certificate, you need to validate that it was
       actually them that sent you the certificate, and that it was not modified in transit.  If  you  add  that
       certificate  to  your  CA, you are trusting the certificate, and you better make sure (with fingerprints,
       generally, see the openssl docs for details) that it came from a trusted entity.

       The hardest part of cryptography in general is key  management.   Breaking  cryptographic  algorithms  is
       really hard.  Getting people to divulge private keys or use the wrong keys is a lot easier.

       For  more on cryptography in general, and cryptography and trust, Bruce Schneier has some excellent books
       on the subject.

IPv6, IPv4, and host names

       Note that a single hostname may result in more than one address.  For instance, it may have both an  IPv4
       and IPv6 address.  These are treated just like multiple hostnames.  For instance, if you use localhost as
       a host name, you generally get the IPv4 and IPv6 version:

              $ gensiot -a -p tcp,localhost,1234
              Address 0(0): ipv6,::1,1234
              Address 1(0): ipv4,127.0.0.1,1234

       The hostname may be prefixed with ipv4 or ipv6, which will force  the  connections  to  those  protocols.
       Specifying ipv6n4 will create a socket that is IPv6 but will handle IPv4 connections.

       Note that using ipv6n4 will not automatically create a socket that is available to IPv4.  You can do, say
       tcp,ipv6n4,::1,1234 and it will work, but since ::1 is not IPv4, you won't be able  to  get  to  it  from
       IPv4.  You have to specify an IPv4 address, like: tcp,ipv6n4,127.0.0.1,1234 which will result in a single
       IPv6 socket mapped into IPv4 space:

              $ gensiot -a -p tcp,ipv6n4,localhost,1234
              Address 0(0): ipv6,::ffff:127.0.0.1,1234

       If you do not specify a hostname on an accepting gensio (like sctp,1234) it  will  only  create  an  IPv6
       socket  that  is  IPv4  mapped.   This  way  it  will accept both IPv4 and IPv6 connections.  Even though
       getaddrinfo would normally return two addresses, only the IPv6 one is  used  unless  there  are  no  IPv6
       addresses configured where it will return an IPv4 address.

       In  general,  for  connecting  gensios  only  the  first address that is found will be used.  SCTP is the
       exception, it will do multi-homing on all the addresses that come up.  Do  you  may  need  to  be  fairly
       specific with addresses.

       In general IPv6 addresses are preferred if both are available.

gtime

       Time  consists  of  a set of numbers each followed by a single letter.  That letter may be 'D', 'H', 'M',
       's', 'm', 'u', or 'n', meaning days, hours, minutes, seconds, milliseconds, microseconds, or nanoseconds.
       So, for instance, "10D5H4M9s100u" would be ten days, 5 hours, 4 minutes, 9 seconds, 100 microseconds.  If
       a plain number with no letter at the end is given, the value may default to a specific unit.   That  will
       be specified by the specific gensio.

TCP

       tcp[(<options>)][,<hostname>],<port>[[,<hostname>],<port>[...]]
       hostname = [ipv4|ipv6|ipv6n4,]<name>

       A TCP connecting gensio must have the hostname specified.  Multiple hostname/port pairs may be specified.
       For a connecting TCP gensio, each one will be tried in sequence until a connection is  established.   For
       acceptor gensios, every specified hostname/port pair will be listened to.

   Dynamic Ports
       For  accepters,  if  the  port is specified as zero, a random port in the dynamic port range specified by
       IANA will be chosen.  If more than one address  is  present,  the  same  port  will  be  chosen  for  all
       addresses.    You   can   fetch  the  port  using  the  gensio_acc_control()  function  with  the  option
       GENSIO_ACC_CONTROL_LPORT.

   Out Of Band Data
       TCP supports out of band (oob) data, which is data that will  be  delivered  out  of  order  as  soon  as
       possible.   This  comes in a normal read, but with "oob" in the auxdata.  You can send oob data by adding
       "oob" to the write auxdata, but oob writes are limited to 1 byte and writing any more than  this  results
       in undefined behavior.  Note that "oobtcp" is also delivered and accepted in auxdata, so you can tell TCP
       oob data from other oob data.

   Options
       In addition to readbuf, the tcp gensio takes the following options:

       nodelay[=true|false]
              Sets nodelay on the socket.

       laddr=<addr>
              An address specification to bind to on the local socket to set the local address.

       reuseaddr[=true|false]
              Set SO_REUSEADDR on the socket, good for accepting gensios only.  Defaults to true.

       tcpd=on|print|off
              Accepter only, sets tcpd handling on the socket.  If "on", tcpd is enforced and the connection  is
              just  closed on a tcpd denial.  "print" is like on, except it writes "Access Denied" on the socket
              before closing it.  "off" disabled tcpd handling on the socket.  Defaults to on.  Not available if
              tcpd is disabled at compile time.

       tcpdname=<name>
              Accepter  only,  sets the name to use for tcpd access control.  This defaults to "gensio", and the
              default can be overridden with gensio_set_progname().  This option allows you to override it on  a
              per-gensio accepter basis.  Not available if tcpd is disabled at compile time.

   Remote Address String
       The  remote  address  will  be  in the format "[ipv4|ipv6],<addr>,<port>" where the address is in numeric
       format, IPv4, or IPv6.

   Remote Address
       TCP returns a standard struct sockaddr for GENSIO_CONTROL_RADDR_BIN control.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const struct gensio_addr *"

UDP

       udp[(<options>)][,<hostname>],<port>[[,<hostname>],<port>[...]]
       hostname = [ipv4|ipv6|ipv6n4,]<name>

       A UDP gensio creates a UDP socket, but it makes  it  look  like  an  unrealiable  stream  of  data.   The
       specification is the same as a TCP socket, except that a UDP socket is created, obviously.

       The  semantics  of  a  UDP  socket  are  a  little  bit  strange.   A  connecting  UDP  socket  is fairly
       straightforward, it opens a local socket and sends data to the remote socket.

       An accepter gensio is not so straightforward.  The accepter gensio will create a new accepted gensio  for
       any  packet  it  receives  from  a new remote host.  If you disable read on any of the accepted gensio or
       disable accepts on the accepting gensio, it will stop all reads  on  all  gensios  associated  with  that
       accepting gensio.

       Note  that  UDP  accepter  gensios  are  not  really  required for using UDP, the are primarily there for
       handling ser2net accepter semantics.  You can create two connecting UDP gensios and  communicate  between
       them.

       UDP gensios are not reliable, but are obviously packet-oriented.

       Port 0 is supported just like TCP for accepters, see Dynamic Ports in the TCP section above for details.

       The destination address defaults to the one specified on the gensio specifier (for connecting gensios) or
       the remote address that initiated the connection (for accepting gensios), but  may  be  overridden  using
       "addr:<addr>" in the write auxdata.

   Options
       In addition to readbuf, the udp gensio takes the following options:

       laddr=<addr>
              An address specification to bind to on the local socket to set the local address.

       nocon[=true|false]
              Don't  be  connection  oriented,  just  receive  all packets and deliver them without establishing
              connections.  Only valid for the client gensio.  The receive address is passed  into  the  auxdata
              prefixed by "addr:", this is the address formatted by gensio_addr_to_str().

       mloop[=true|false]
              If  false,  multicast  packets  transmitted will not be received on the local host.  If true, they
              will.

       mttl=[1-255]
              Set the multicast time-to-live value.  The default is 1, meaning  multicast  stays  in  the  local
              network.   Increasing this value increases the number of hops over multicast routers a send packet
              will traverse.

       mcast=<addr>
              Add an address to receive multicast packets on.  There is no port number, this is just  addresses.
              You can specify multiple addresses in a single multicast option and/or the multicast option can be
              used multiple times to add multiple multicast addresses.

       reuseaddr[=true|false]
              Set SO_REUSEADDR on the socket, good for connecting and accepting gensios.  Defaults to false.

   Remote Address String
       The remote address will be in the format "[ipv4|ipv6],<addr>,<port>" where  the  address  is  in  numeric
       format, IPv4, or IPv6.

   Remote Address
       UDP returns a standard struct sockaddr for GENSIO_CONTROL_RADDR_BIN control.

   UDP Multicast
       Multicast  can  be  used  on UDP gensios with the nocon, maddr and laddr options.  To set up a multicast,
       create a client UDP gensio and set the laddr for the receive port and  the  destination  address  to  the
       multicast and enable nocon, like:

              "udp(mcast='ff02::1',laddr='ipv6,3000',nocon),ff02::1,3000"

       and  you  will  receive  and send data on the multicast address.  The laddr option is required to set the
       port to receive on.  It means you will have a local address, too, and will receive packets on that, too.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const struct gensio_addr *"

SCTP

       sctp[(<options>)][,<hostname>],<port>[[,<hostname>],<port>[...]]
       hostname = [ipv4|ipv6|ipv6n4,]<name>

       An SCTP gensio is specified like a UDP or  TCP  one.   However,  the  semantics  are  different.   For  a
       connecting  gensio,  it will attempt to create a multi-homed connect with all the specified hostnames and
       ports.  All the ports must be the same.

       For an accepter gensio, it will create a single socket with  all  the  specified  addresses  as  possible
       destinations.  Again, all the ports must be the same.

       SCTP  gensios are reliable.  They are not, at the moment, packet oriented.  There is currently no support
       of SCTP_EXPLICIT_EOR in the Linux implementation of SCTP, and without that it would be hard  to  make  it
       packet oriented.

       When  specifying IPv6 addresses that might map to IPv4, you must be careful.  If one side can do IPv4 and
       the other side can only do IPv6, the connection may come up,  but  will  disconnect  quickly  because  it
       cannot communicate on the IPv4 side.  For instance, the following accepter:

              tools/gensiot -a "sctp,ipv6,::,1234"

       and the following connector:

              tools/gensiot "sctp,::1,1234"

       will fail this way because the connector will support IPv4 add but the accepter will not.

   Nagle and SCTP
       SCTP implements the Nagle algorithm by default, which can interact badly if sack_freq is set to more than
       one.  At least Linux defaults sack_freq  to  2,  but  the  gensio  overrides  this  to  avoid  surprising
       behaviour.   What  happens is in some situations you can get an outstanding packet that is unacked, since
       sack_freq is greater than one.  The Nagle algorithm will not send any new data  until  any  already  sent
       data  is acked.  So one end is waiting for a new packet to send a sack, and the other end is holding data
       until it gets a sack.  So you get stuck waiting for the sack_delay where the sack will go  out  and  kick
       things back off again.

       You need to be aware of this if you modify sack_freq.

   Options
       In addition to readbuf, the sctp gensio takes the following options:

       instreams=<n>

       ostreams=<n>
              These specify the number of incoming and outgoing streams for the connection.  The default is one.
              The stream is given in the auxdata for read and write in the format "stream=<n>".

       sack_freq=<n>

       sack_delay=<n>
              These specify the handling of selective acknowledgements (sacks).  sack_freq sets  the  number  of
              outstanding  packets  that  must  be received before sending a sack.  The default is 1, meaning it
              doesn't wait at all.  sack_delay sets the maximum time  before  a  sack  is  sent  if  outstanding
              packets are present, in milliseconds.  The default is 10, but this is disabled if sack_freq is set
              to 1.  Setting either of these to 0 enables the system defaults.

       nodelay[=true|false]
              Sets nodelay on the socket.

       laddr=<addr>
              An address specification to bind to on the local socket to set the local address.

       reuseaddr[=true|false]
              Set SO_REUSEADDR on the socket, good for accepting gensios only.  Defaults to true.

              Port 0 is supported just like TCP for accepters, see Dynamic Ports in the TCP  section  above  for
              details.

              SCTP  support out of band (oob) data, which is data that will be delivered out of order as soon as
              possible.  This comes in a normal read, but with "oob" in the auxdata.  You can send oob  data  by
              adding "oob" to the write auxdata.

              See documentation on SCTP for more details.

   Remote Address String
       The  remote  address  will  be in the format "[ipv4|ipv6],<addr>,<port>[;[ipv4|ipv6],<addr>,<port>[...]]"
       where the address is in numeric format, IPv4, or IPv6.  Each remote address for the  SCTP  connection  is
       listed.

   Remote Address
       SCTP returns a packed struct sockaddr for GENSIO_CONTROL_RADDR_BIN control, per SCTP semantics.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const struct gensio_addr *"

UNIX

       unix[(<options>)],<socket_path>

       Create a unix domain socket as an accepter, or connect to a unix domain socket as a connecter.

       A  file  will be created with the given socket path, you must have permissions to create a writeable file
       in that location.  If the file already exists, an error will be returned on an accepter socket unless you
       specify delsock which will cause the file to be deleted.

       You  should  read  the  unix(7)  man  page  for  details  on  the  semantics of these sockets, especially
       permissions.  The options below allow setting various permission and ownership of the file, but this  may
       not  have  any  effect  on  who  can  open socket depending on the particular operating system.  Portable
       programs should not rely on these permissions for security.  Also note that Linux remote credentials  are
       not currently implemented.

   Options
       In addition to readbuf, the unix gensio takes the following options:

       delsock[=true|false]
              If the socket path already exists, delete it before opening the socket.

       umode=[0-7|[rwx]*]
              Set  the  user  file mode for the unix socket file.  This is the usual read(4)/write(2)/execute(2)
              bitmask per chmod, but only for the user portion.  If a mode is specified, all other modes default
              to  "6" (rw) +unless they are specified, and the final mode is modified by the umask +per standard
              *nix semantics.  If no mode is specified, it is set to +the default and not modified.   Note  that
              the perm option below is +probably a better way to set this.

       gmode=[0-7|[rwx]*]
              Set the group file mode for the unix socket file, see umode for details.

       omode=[0-7|[rwx]*]
              Set the other file mode for the uix socket file, see umode for details.

       perm=[0-7][0-7][0-7]
              Set  the  full mode for the unix socket file per standard *nix semantics, modified by umask as the
              above mode operations are.

       owner=<name>
              Set the owner of the unix socket file to the given user.

       group=<name>
              Set the group of the unix socket file to the given group.

   Remote Address String
       The remote address will be: "unix,<socket path>".

   Remote Address
       UNIX returns a standard struct sockaddr_un for GENSIO_CONTROL_RADDR_BIN control.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const struct gensio_addr *"

serialdev

       serialdev[(<options>)],<device>[,<serialoption>[,<serialoption>]]

       A serialdev connection is a local serial port.  The device is a /dev/xxx type, and should be real  stream
       device  of  some  type that normal termios or serial processing work on.  For non-serial devices, use the
       "dev" gensio.

       This is, no surprise, a serial gensio.

       You can also use "sdev" instead of "serialdev" for shorthand.

       One problem with serialdev and UUCP locking is that if you fork() a process while one is open, the forked
       process  will  have the serialdev but the value in the UUCP lockfile will be incorrect.  There's not much
       that can be done about this, so be careful.

   Options
       In addition to readbuf, the serialdev gensio takes the following options:

       uucplock[=true|false]
              Enable or disable UUCP locking on the device.  The default  is  true  for  everything  except  pty
              devices and /dev/tty.  This is ignored on systems that don't support this.

       flock[=true|false]
              Enable  or  disable  flock  locking  on  the  device.   The  default is true for everything except
              /dev/tty.  Note that this does both an "flock(fd, LOCK_EX | LOCK_NB)" and an "ioctl(fd, TIOCNXCL)"
              to lock the device.  This is ignored on systems that don't support this.

       drain_time=off|<time in 100ths of a second>
              The  total amount of time to wait for the data to be sent on the serial port at close time.  Close
              will be delayed this amount of time, or until all the data is transmitted.  Default is off.   When
              setting the default value for this, "off" will not be accepted, use -1 instead.

       char_drain_wait=off|<time in 100ths of a second>
              At  close  time, if this much time elapses and no character is sent, finish the close.  Default is
              50 (.5 seconds).  Note that if both this and drain_time are off, if the serial  port  is  hung  on
              flow  control,  it  will  never close.  When setting the default value for this, "off" will not be
              accepted, use -1 instead.

       wronly[=true|false]
              Set the device to write only.  Default is false.  rdonly[=true|false] Set the device to read only.
              Default is false.

   Serialoptions
       There are a plethora of serialoptions, available as defaults:

       [speed=]<speed><parity><databits><stopbits>
              This  is  a  normal  serial port configuration specification, like "9600N81".  The "speed=" at the
              beginning is optional, but "speed" is a default type for this.

       wronly[=true|false]
              This option is deprecated, use the "dev" gensio for non-serial port devices and the wronly  option
              in the parameters.

              Set  the  device  to  write only.  No termios definition is done on the port.  This can be done to
              talk to a line printer port, for instance.  False by default.  Note that  for  historical  reasons
              this  is  different  than  the  wronly  option set in the parameters, this one sets both turns off
              termio process and sets wronly.

       nobreak[=true|false]
              Clear the break line at start (or don't clear it).  Default it to not clear it (false).

       rs485=off|<delay rts before send>:<delay rts after send>[:<conf>[:<conf>]]
              Set up RS-485 for the serial port.  The first two parameters set the RTS delay  (in  milliseconds)
              of  RTS  before  and after sending.  The conf values can be: "rts_on_send" - RTS set when sending,
              "rts_after_send" - RTS set after sending, "rx_during_tx" - can receive and transmit  at  the  same
              time, and "terminate_bus" - enable bus termination.

              Using  "off"  will  disable  rs485;  that is useful for overriding a user-defined default setting.
              Default is "off".

       xonxoff[=true|false]
              Enable/disable xon/xoff flow control.  Default is false.

       rtscts[=true|false]
              Enable/disable rts/cts flow control.  Default is false.

       local[=true|false]
              Ignore/don't ignore the modem control lines.  The default it to not ignore them (false).  However,
              if you don't ignore the modem control lines, it can result in long shutdown delays.

       dtr[=on|off]
              Force  the DTR line to be on or off when the gensio is opened.  Note that the order of the dtr and
              rts options matter.  Whichever comes first in the options will be set first.  This can  be  useful
              if the lines need to be sequenced in a certain order for the piece of hardware involved.

       rts[=on|off]
              Force the RTS line to be on or off when the gensio is opened.  See the dtr section above for notes
              on ordering of lines.

       hangup-when-done[=true|false]
              Lower/don't lower the modem control lines when the gensio is closed.  The default  is  not  modify
              the  value.  On Unix, this will modify HUPCL value set on the termios after close, because there's
              no other real way to do that.  On Windows, it will clear DTR and RTS on close.

              On the default for this, it's a integer, -1 means don't set the value, 0 means turn off,  1  means
              turn on.

       custspeed[=true|false]
              Allow/don't  allow  setting of custom baud rates.  Ignored if custom baud rates are not supported.
              Normally only standard baud rates are supported (1200, 2400, etc).  If supported by the  hardware,
              this allows any arbitrary value to be set.

   Remote Address String
       The    remote    address    string    is    the   device   and   serial   parms,   in   a   format   like
       "9600N81[,<option>[,<option>[...]]]".  Options are one of:  XONXOFF,  RTSCTS,  CLOCAL,  HANGUP_WHEN_DONE,
       RTSHI, RTSLO, DTRHI, DRLO, offline.

   Remote ID
       The remote ID for the serial dev is the file descriptor returned as an integer.

   Direct Allocation x
       Allocated as a terminal gensio with gdata as a "const char *" with the device and parameters string.

dev

       dev[(<options>)],<device> This is like a serialdev gensio, but doesn't do any serial port processing like
       termios or break processing.  This can be used for /dev/lpX devices for instance.  This is read/write  by
       default,  you  must  set  the  wronly option to disable read access for a write-only device and rdonly to
       disable write access for read-only devices.

       This takes the same options as serialdev except  that  it  does  not  do  locking.   The  drain_time  and
       char_drain_wait options may or may not work.  It does not take serial options.

stdio

       accepter = stdio[(options)]
       connecting = stdio[(options)],<program>

       The stdio gensio is a fairly strange one, but it's fairly useful.

       A  connecting  stdio  gensio  runs  the  given program (unless self is set as an option) and connects its
       standard input and output to the gensio's main channel.  So it's easy to run a program and interact  with
       it.  If you want to get stderr from the gensio, open a channel on the main channel gensio, see below.

       NOTE:  Though  epoll()  doesn't  work with normal files, the stdio gensio has special handling for normal
       files so they mostly work.  This can have surprising side effects if you use  stdin  as  a  normal  file.
       When  you hit the end of stdin, the stdio gensio will return GE_REMCLOSE and you may shut down the gensio
       and possibly lose any output going to stdout.  Use the file gensio if you can.

       For connecting gensios, in the forked process, the code will set the effective (and saved) uid  and  guid
       to  the  current real uid and guid if the effective and real uids are different.  This way a user can set
       the real uid and gid to what they want the program to run under, but keep the effective uid  and  gid  to
       the (probably root) values so they can be restored to those values after opening the pty.  The group list
       is also set to the groups the real userid is in.  Note that nothing is done if  the  effective  and  real
       userids are the same.

       If  you  have  both  stdin/stdout  and stderr opened, you must close both of them to completely close the
       gensio.  You cannot re-open the gensio until both are closed.

       The connecting gensio support the GENSIO_CONTROL_ENVIRONMENT control to allow the environment to  be  set
       for the new process.

       An  accepting  gensio  immediately  does a connection when started and connection stdin and stdout of the
       running program to the gensio.

   Options
       In addition to readbuf, a connecting stdio takes the following options:

       self[=true|false]
              Instead of starting a program, connect to the running program's stdio.  This is  the  same  as  an
              accepting stdio gensio, except you don't have to go through the accept process.

       console[=true|false]
              Like  self,  except  connect  to  the  running  program's  console  device,  /dev/tty  on Unix and
              CONIN$/CONOUT$ on Windows.  Useful for reading passwords and such.

       start-dir=path
              Start the subprogram in the given path instead of the current directory.

       raw[=true|false]
              For a "self", console, or accepter version of the gensio, put  the  I/O  in  "raw"  mode,  meaning
              character at a time, turn off ^C, etc.  This will fail on pipes or files.

       stderr-to-stdout
              Send standard error output to standard out instead of having a separate channel for it.

       noredir-stderr
              Do not modify the stderr for the program, use the calling program's stderr.  This can be useful if
              you want to see stderr output from a program.

   Channels
       The stdio connecting gensio that start another program does not  provide  stderr  as  part  of  the  main
       gensio.  You  must create a channel with gensio_alloc_channnel() and then open it get stderr output.  The
       args for gensio_alloc_channel() may be an optional "readbuf=<num>" and sets the size of the input buffer.

   Remote Address String
       The remote address string is either "stdio,<args>" for the main channel or "stderr,<args>" for the  error
       channel.   The  args  will  be  a  set  of  quoted strings with a space between each string, one for each
       argument, with '"' around each argument, each '"' in the string converted to '\"' and  each  '\'  in  the
       string converted to '\\'.

   Remote ID
       The remote ID is the pid for the remote device, only for connecting gensios that start a program, not for
       any other type.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const char * const args[]" for the gensio.  gdata is  not
       used for the accepter.

echo

       connecting = echo[(options)]

       The echo gensio just echos back all the data written to it.  Useful for testing.

   Options
       In addition to readbuf, a connecting echo takes the following options:

       noecho[=true|false]
              Instead of echoing the data, just become a data sink.

       data=<str>
              Supply  the given data as the data to be read.  When combined with noecho, it will create a gensio
              that just supplies the given data then returns a GE_REMCLOSE when done.

   Remote Address String
       The remote address string is "echo".

   Direct Allocation
       Allocated as a terminal gensio, gdata is not used.

file

       connecting = file[(options)]

       The file gensio opens an (optional) input file and (optional) output file for the gensio.  If you need to
       read/write  a  file  in  gensio,  you  must  use  this.   Semantics  on files for stdio do not alway work
       correctly.

       If an input file is specified, data will be read from the input file and delivered on the read  interface
       of the gensio until end of file, when the GE_REMCLOSE error will be returned.

       If  an  output  file is specified, data will be written to the output file on writes.  The output file is
       always ready to receive data.

   Options
       In addition to readbuf, a connecting file takes the following options:

       infile=filename
              Set the input filename.

       outfile=filename
              Set the output filename.

       read_close[=true|false]
              If this is true (the default), cause a GE_REMCLOSE error on read when all the file data is  ready.
              If  false, just stop returning data and don't do the GE_REMCLOSE.  This is useful if you just want
              to inject a bunch of data then do nothing.

       create[=true|false]
              Create the output file if it does not exist.  Ignored for read.

       append[=true|false]
              Open the file in append mode.  If not specified, it will be opened at the beginning  of  the  file
              and if writing, it will overwrite.  Ignored for read.

       trunc[=true|false]
              Truncate the file on open.  All data will be deleted from the file when opened.  Ignored for read.

       binary[=true|false]
              Open  the  file  in  binary mode.  This is ignored on *nix systems, but for Windows it affects how
              newlines are handled.

       umode=[0-7|[rwx]*]
              Set  the  user  file  mode  for  the  file  if  the  file  is  created.    This   is   the   usual
              read(4)/write(2)/execute(2)  bitmask  per  chmod,  but  only  for  the user portion.  If a mode is
              specified, all other modes default to "6" (rw) +unless they are specified, and the final  mode  is
              modified  by  the  umask +per standard *nix semantics.  If no mode is specified, it is set to +the
              default and not modified.  Note that the perm option below is +probably a better way to set this.

       gmode=[0-7|[rwx]*]
              Set the group file mode for the file if the file is created, see umode for details.

       omode=[0-7|[rwx]*]
              Set the other file mode for the file if the file is created, see umode for details.

       perm=[0-7][0-7][0-7]
              Set the full mode for the file per standard *nix semantics, modified by umask as  the  above  mode
              operations are.

   Remote Address String
       The remote address string is "file([infile=<filename][,][outfile=<filename>])".

   Direct Allocation
       Allocated as a terminal gensio, gdata is not used.

dummy

       accepter = dummy

       The  dummy  gensio accepter is useful for place holding, where you don't want a real working accepter but
       need to put something.

       As you might guess, it doesn't do anything.

   Direct Allocation
       Allocated as a terminal gensio, gdata is not used.

ipmisol

       ipmisol[(options)],<openipmi arguments>[,ipmisol option[,...]]

       An ipmisol gensio creates an IPMI Serial Over LAN  connection  to  an  IPMI  server.   See  the  OpenIPMI
       documentation for information on the arguments.

       This is a serial gensio, but the baud rate settings are fairly limited.

   Options
       In addition to readbuf, the ipmisol gensio takes the following options:

       writebuf=<n>
              to set the size of the write buffer.

       It also takes the following ipmisol options:

       9600, 19200, 38400, 57600, 115200
              Baud  rate,  9600 by default.  Anything after the number is ignored, for compatibility with things
              like "N81".  You cannot set those values for ipmisol, they are fixed at "N81".

       nobreak[=true|false]
              Disable break processing.  False by default.

       authenticated[=true|false]
              Enable or disable authentication.  True by default.

       encrypted[=true|false]
              Enable or disable encrypted.  True by default.

       deassert-CTS-DCD-DSR-on-connect[=true|false]
              False by default

       shared-serial-alert=fail|deferred|succeed
              Behavior of handling serial alerts.  fail by default.

       ack-timeout=<number>
              The time (in microseconds) when an ack times out.  1000000 by default.

       ack-retries=<number>
              The number of times (ack-timeouts) an ack is re-sent before giving up.  10 by default.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const char *".

telnet

       accepter = telnet[(options)]
       connecting = telnet[(options)]

       A telnet gensio is a filter that sits on top of another gensio.  It runs  the  standard  telnet  protocol
       andn support RFC2217.

   Options
       In addition to readbuf, the telnet gensio takes the following options:

       writebuf=<n>
              set the size of the write buffer.

       rfc2217[=true|false]
              enable  or  disable  RFC2217  mode  for this gensio.  If this is enabled and the remote end of the
              connection supports RFC2217 also, the gensio will be set up as a serial  gensio  and  you  can  do
              normal serial gensio handling on it.

       winsize[=true|false]
              enable or disable RFC1073, window size change notification.  Default is false.

       mode=client|server
              Set  the  telnet  mode  to  client  or  server.  This lets you run a telnet server on a connecting
              gensio, or a telnet client on an accepter gensio.

   Remote info
       telnet passes remote id, remote address, and remote string to the child gensio.

ssl

       accepter = ssl[(options)]
       connecting = ssl[(options)]

       An SSL gensio runs the SSL/TLS protocol on top of another gensio.  That gensio must be reliable.

       Use is pretty straightforward.  The hardest part about using the  SSL  gensio  is  the  certificates.   A
       server SSL gensio must be given a certificate and a key.  A client SSL gensio must be given a certificate
       authority.  A client will user the certificate authority  to  verify  that  the  server  has  the  proper
       certificate and keys.

       The gensio has options to have the server request the certificate from the client and validate it.

       SSL gensios are reliable.  They are also packet-oriented.

   Options
       In addition to readbuf, the SSL gensio takes the following options:

       writebuf=<n>
              set the size of the write buffer.

       CA=<filepath>
              Set  a  place  to  look  for  certificates for authorization.  If this ends in a "/", then this is
              expected to be a directory that contains files with certificates that must be hashed  per  OpenSSL
              (see the "openssl rehash" command for details.  Otherwise it is a single file that contains one or
              more certificates.  The default CA path is used if not specified.  Note that setting  this  to  an
              empty string disables it, so you can override a default value if necessary.

       key=<filename>
              Specify  the file to get the private key for the server.  This is required for servers.  It may be
              specified for clients, and is required for the client if the server requires a certificate (it has
              CA set).

       cert=<filename>
              Specify the file that contains the certificate used for the connection.  If this is not specified,
              the certificate is expected to be in the key file.  Note that setting  this  to  an  empty  string
              disables it, so you can override a default value if necessary.

       mode=client|server
              Normally an accepter gensio is in server mode and a connecting gensio is in client mode.  This can
              be used to switch the roles and run in SSL server mode on a connecting gensio, or vice versa.

       con-timeout=<gtime>
              Set the timeout for a connection to complete.  If the connect process does not  complete  in  this
              amount  of  time,  the  connection  will  be dropped.  The default is 60 seconds.  See the "gtime"
              section for more info on how to set the time.  Note that the default setting  for  con-timeout  is
              not a gtime, it is an integer in seconds.

       clientauth[=true|false]
              Normally  a  client  is  not  authorized  by  the server.  This requires that the client provide a
              certificate and authorizes that certificate.  Ignored for client mode.

       allow-authfail[=true|false]
              Normally if the remote end certificate is not valid, the SSL gensio  will  close  the  connection.
              This  open  allows the open to succeed with an invalid or missing certificate.  Note that the user
              should verify that authentication is set using gensio_is_authenticated().

              Verification of the common name is not done.  The application should do this,  it  can  fetch  the
              common name and other certificate data through a control interface.

              You  can  use  self-signed  certificates  in  this  interface.   Just  be  aware  of  the security
              ramifications.  This gensio is fairly flexible, but you must use it carefully  to  have  a  secure
              interface.

              The  SSL gensio will call the gensio event callback (client) or the gensio acceptor event callback
              (server)  after  the  certificate  is   received   but   before   it   is   validated   with   the
              GENSIO_EVENT_PRECERT_VERIFY  or  GENSIO_ACC_EVENT_PRECERT_VERIFY  events.  This allows the user to
              validate data from the certificate (like common name)  with  GENSIO_CONTROL_GET_PEER_CERT_NAME  or
              set a certificate authority for the validation with GENSIO_CONTROL_CERT_AUTH.

   Remote info
       ssl passes remote id, remote address, and remote string to the child gensio.

certauth

       accepter = certauth[(options)]
       connecting = certauth[(options)]

       A  certauth  gensio  runs  an  authentication  protocol to on top of another gensio.  That gensio must be
       reliable and encrypted.

       This is like the reverse of SSL.  The client has a key and certificate,  the  server  has  a  certificate
       authority (CA).  This also supports password authentication.

       Once  authentication  occurs,  this gensio acts as a passthrough.  The readbuf option is not available in
       the gensio.

   Options
       The certauth gensio takes the following options:

       CA=<filepath>
              Set a place to look for certificates for authorization.  If this ends  in  a  "/",  then  this  is
              expected  to be a directory that contains files with certificates that must be hashed per OpenSSL,
              see the gensio-keygen(1) in the rehash section for details.  Otherwise it is a  single  file  that
              contains  one  or  more  certificates.   The default CA path for openssl is used if not specified.
              This is used on the server only, it is ignored on clients.  Note that setting  this  to  an  empty
              string disables it, so you can override a default value if necessary.

       key=<filename>
              Specify  the  file  to  get  the private key for the client.  This is required for clients.  It is
              ignored on server.

       cert=<filename>
              Specify the file to get the private key for the client.  This is  required  for  clients.   It  is
              ignored  on  server.  If this is not specified, the certificate is expected to be in the key file.
              Note that setting this to an empty string disables it, so you can  override  a  default  value  if
              necessary.

       username=<name>
              Specify  a  username to authenticate with on the remote end.  This is required for the client.  It
              is ignored on the server.

       service=<string>
              Set the remote service requested by the client.  Optional,  but  the  other  end  may  reject  the
              connection if it is not supplied. Ignored on the server.

       password=<string>
              Specify the password to use for password authentication.  This is not recommended, the callback is
              more secure to use.

       mode=client|server
              Normally an accepter gensio is in server mode and a connecting gensio is in client mode.  This can
              be used to switch the roles and run in server mode on a connecting gensio, or vice versa.

       allow-authfail[=true|false]
              Normally  if  the  remote  end  certificate  is  not  valid,  the  certauth  gensio will close the
              connection.  This open allows the open to succeed with an invalid or  missing  certificate.   Note
              that the user should verify that authentication is set using gensio_is_authenticated().

       use-child-auth[=true|false]
              If  the  child  gensio  is  authenticated,  then  do  not  run the protocol, just go straight into
              passthrough mode and don't do any authentication.

       enable-password[=true|false]
              On the server, allow passwords for login.  On the client, send a password if asked  for  one.   By
              default  passwords  are disabled.  Use of passwords is much less secure than certificates, so this
              is discouraged.

       enable-2fa[=true|false]
              On the server, request 2-factor authentication data from the client.   This  is  only  useful  for
              situations  where  the  2-factor  data is known before startup, like Google Authenticator or other
              things of that nature.  It is not useful for text/email types of things that send the  data  after
              the  connection  is  initiated.   But  those  are  usually  interactive  and  can  be handled with
              interactive methods.

       2fa=<string>
              On the client, provide the given 2-factor authentication data to the server if it asks for it.

       Verification of the common name is not done.  The application should do this, it  can  fetch  the  common
       name  and  other  certificate  data  through  a  control interface.  It may also use the username fetched
       through the control interface.

       con-timeout=<gtime>
              Set the timeout for a connection to complete.  If the connect process does not  complete  in  this
              amount  of  time,  the  connection  will  be dropped.  The default is 60 seconds.  See the "gtime"
              section for more info on how to set the time.  Note that the default setting  for  con-timeout  is
              not a gtime, it is an integer in seconds.

              You  can  use  self-signed  certificates  in  this  interface.   Just  be  aware  of  the security
              ramifications.  This gensio is fairly flexible, but you must  use  it  carefully  to  have  secure
              authentication.

              The  certauth  gensio  has 4 major callbacks dealing with authentication of the user.  They may or
              may not be called depending on the circumstances.  The normal events come in if you have allocated
              a  gensio  and  are doing an open.  The _ACC_ events come in if it is coming in from an accept and
              there is no gensio reported yet.  In the _ACC_ case, be careful, do not use the given  gensio  for
              anything but checking certificate and username parameters, and do not save it.

              All  these  calls  should  return  0  if  they  want  the  authentication  to immediately succeed,
              EKEYREJECTED if they reject the authentication, ENOTSUP if they want certauth to ignore that  part
              of the authentication, or any other errno will result in the connetion being shut down.

              The callbacks are:

       GENSIO_EVENT_AUTH_BEGIN / GENSIO_ACC_EVENT_AUTH_BEGIN
              On  the  server  side,  this  is  called  when to authentication is requested buy the client.  The
              username will be available if the user provided it via GENSIO_CONTROL_USERNAME.

       GENSIO_EVENT_PRECERT_VERIFY / GENSIO_ACC_EVENT_PRECERT_VERIFY
              On the server side, thi is called after the  certificate  has  been  received  but  before  it  is
              verified.   The  user  can  use this to query the certificate and update the certificate authority
              based on username or certificate information.

       GENSIO_EVENT_VERIFY_PASSWORD / GENSIO_ACC_EVENT_VERIFY_PASSWORD
              On the server side, this is called if the  certificate  verification  has  failed  and  after  the
              password  has  been  requested  from  the  remote  end.   The password is passed in, it is cleared
              immediately after this call.

       GENSIO_EVENT_REQUEST_PASSWORD / GENSIO_ACC_EVENT_REQUEST_PASSWORD
              On the client side, this is called if the server requests that a password be sent and the password
              is not already set for the gensio.  The requested password is immediately cleared after being sent
              to the server.

   Remote info
       certauth passes remote id, remote address, and remote string to the child gensio.

mux

       accepter = mux[(options)]
       connecting = mux[(options)]

       A mux gensio is a gensio filter that allows one or more channels to be created on top of a single gensio,
       multiplexing  the  connection.   Each channel has full individual flow-control.  The channels are message
       oriented as described above, and use can use a  mux  without  additional  channels  to  just  do  message
       demarcation.  They also support out-of-bounds messages.

   Options
       A mux gensio takes the following options:

       max_channels=<n>
              Allow  at  most <n> channels to be created in the mux.  The default is 1000.  The minimum value of
              <n> is 1, the maximum is 65536.

       service=<string>
              Set the remote service requested by the client.  Optional,  but  the  other  end  may  reject  the
              connection if it is not supplied. Ignored on the server.

       mode=client|server
              By  default  a  mux  accepter is a server and a mux connecter is a client.  The protocol is mostly
              symmetric, but it's hard to kick things off properly if both sides  try  to  start  things.   This
              option lets you override the default mode in case you have some special need to do so.

       When  the  open  is  complete on the mux gensio, it will work just like a transparent filter with message
       demarcation.  In effect, you have one channel open.

   Creating Channels
       To create a channel, call the gensio_alloc_channel() function on the mux gensio.  This will return a  new
       gensio  that  is  a  channel on the mux gensio.  You can pass in arguments, which is an array of strings,
       currently readbuf, writebuf, and service are accepted.  The service you set  here  will  be  set  on  the
       remote  channel  so  the  other  end can fetch it.  The new channel needs to be opened with gensio_open()
       before it can be used.

       As you might imaging, the other end of a mux needs to know about the new channel.   If  one  end  (either
       end,  doesn't matter) calls gensio_alloc_channel() and then opens the new channel, the other end will get
       a GENSIO_EVENT_NEW_CHANNEL event as described in the Streams and Channels section.  You can call it using
       any mux channel.  The first element in the auxdata is the service.

       You can modify the service value after you allocate the channel but before you open it.

   Out Of Band Messages
       mux  support  out  of  band  (oob)  data, which is data that will be delivered normally.  This comes in a
       normal read, but with "oob" in the auxdata.  You can send oob data by adding "oob" to the write  auxdata.
       You should normally use the "eom" flag so the end of the out of band messages ismarked.

       This is so you can send special data outside of the normal processing of data.

   Mux Events
       As you might imaging, normal data events come through the gensio channel they are associated with.  Close
       events will, too.  If a mux gensio closes abnormally (like the underlying connection fails) you will  get
       a read error on each channel.

       New  channel  events (and other global events coming from lower gensios, like if you are running over ssl
       or telnet) come in through the original gensio normally.  However, you can close  that,  another  channel
       will be chosen to receive those event.  In general, it's best to handle the global events on all channels
       and not assume.

   Closing and Freeing a Mux
       To close a mux gensio, just close all channels associated with it.  There is no  global  close  mechanism
       (you  would not believe the complexity that adds).  Once you have closed a mux gensio, you can re-open it
       with gensio_open().  It will not recreate all the channels for you, you will have one  channel,  and  the
       channel you use to call gensio_open() will become the first channel.

       You cannot re-open individual channels.

       To free a mux gensio, you must free all the channels on it.

pty

       connecting = pty[(options)][,<program>]

       Create a pty and optionally run a program on the other end of it.  With a program specified, this is sort
       of like stdio, but the program is running on a terminal.  Only connection gensios are supported.

       pty has some unusual handling to allow execution of login shells of users from root.

       In Unix type systems, if the first character of the program is '-', it is removed from the  execution  of
       the command but left in argv[0].  This will cause a shell to act as a login shell.

       On  Unix type systems, in the forked process, the code will set the effective (and saved) uid and guid to
       the current real uid and guid if the effective and real uids are different.  This way a user can set  the
       real  uid  and  gid to what they want the program to run under, but keep the effective uid and gid to the
       (probably root) values so they can be restored to those values after opening the pty.  The group list  is
       also  set  to  the  groups  the  real  userid is in.  Note that nothing is done if the effective and real
       userids are the same.

       On Windows, the new process is set to the user in the impersonation token if it is set.   In  that  case,
       the  new  process  will be run in a new process group.  If no impersonation token is set, the new process
       will run as the user of calling process in the same process group as the calling process.

       The pty gensio supports the GENSIO_CONTROL_ENVIRONMENT control to allow the environment to be set for the
       new  process.  GENSIO_CONTROL_ARGS sets the arguments as an argv array.  GENSIO_CONTROL_WIN_SIZE sets the
       terminal size in characters.  GENSIO_CONTROL_START_DIR sets the directory the new process runs in.

       If no program is specified, when the pty gensio is opened it will just create the pty  but  won't  attach
       anything to it.  Another program can open the pty.  You can get the slave pty device by getting the local
       address string.

   Options
       In addition to readbuf, the pty gensio takes the following options.  These options are  only  allowed  if
       the pty is unattached.  ptys with programs run on them need to follow the standard semantics.

       link=<filename>
              create  a symbolic link from filename to the pty name.  This way you can have a fixed reference to
              refer to the pty.  Standard permissions apply.  Without forcelink the open will file  if  filename
              already exists.  Unix only.

       forcelink[=true|false]
              if  link  is  specified,  if  a  file  already  exists where the symbolic link is, replace it.  Be
              careful, it deletes whatever is there indiscriminately.

       start-dir=path
              Start the subprogram in the given path instead of the current directory.

       raw[=true|false]
              causes the pty to be set in raw mode at startup.  This is important for anything that  will  start
              writing  immediately  to the pty.  If you don't set this, echo will be on and writes on the master
              will be echoed back.  In general, this is useful for unattached ptys.  It was added  for  testing,
              but will be usedful in many situations.

       umode=[0-7|[rwx]*]
              Set  the  user file mode for the pty slave.  This is the usual read(4)/write(2)/execute(2) bitmask
              per chmod, but only for the user portion.  If a mode is specified, all other modes default to  "6"
              (rw)  +unless  they  are specified, and the final mode is modified by the umask +per standard *nix
              semantics.  If no mode is specified, it is set to +the default and not modified.   Note  that  the
              perm option below is +probably a better way to set this.

       gmode=[0-7|[rwx]*]
              Set the group file mode for the pty slave, see umode for details.

       omode=[0-7|[rwx]*]
              Set the other file mode for the pty slave, see umode for details.

       perm=[0-7][0-7][0-7]
              Set  the  full  mode  for the pty per standard *nix semantics, modified by umask as the above mode
              operations are.

       owner=<name>
              Set the owner of the slave pty to the given user.

       group=<name>
              Set the group of the slave pty to the given group.

       user=<name>
              Windows only, create the process under the given user instead of the calling process' user.   This
              generally required special privileges.

       passwd=<name>
              Windows  only,  user  must  be  specified  to use.  Log on the user with the given password.  If a
              password is not given, an S4U logon will be attempted, but that may  not  work  so  well  as  some
              things are missing from the access token of the user.

              NOTE: There are significant security issues with passing a password this way.  You must use proper
              password handling.  module=<name> Windows only, user must be specified to  use.   Create  the  new
              user token with the given module.  If not specified, "gensio" is used.

   Remote Address String
       The  remote  address  string  the  program and arguments run on the pty.  The argiuments will be a set of
       quoted strings with a space between each string, one for each argument, with '"'  around  each  argument,
       each '"' in the string converted to '\"' and each '\' in the string converted to '\\'.

   Remote Address
       The  address  is  a  pointer to an integer, the ptym file descriptor is returned.  addrlen must be set to
       sizeof(int) when passed in.

   Local Address String
       This returns the device of the pty, generally /dev/pts/<n>.  This is  useful  for  pty  gensios  with  no
       program,  it allows you to get the value for the other end to connect to.  Note that if you close and re-
       open a pty gensio, you may be a different local address string.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const char * const args[]".

msgdelim

       accepter = msgdelim[(options)]
       connecting = msgdelim[(options)]

       A message delimiter converts an unreliable  stream  (like  a  serial  port)  into  an  unreliable  packet
       interface.   This is primarily to allow a reliable packet interface like relpkt to run on top of a serial
       port.  It does not support streaming of data, so it's not very useful by itself.

       Messages are delimited with a start of message and end of message and have a CRC16 on the end of them.

       This is primarily for use on serial ports and other streams that can munge up  the  data.   Use  the  mux
       gensio for TCP and such.

       The default buffer size is 128 bytes, which is ok for a reasonably fast serial port interface.

   Options
       In addition to readbuf, the msgdelim gensio takes the following options:

       writebuf=<n>
              set the size of the write buffer.

       crc[=on|off]
              Enable/disable  the  CRC  at  the  end  of  the packet.  Useful if you are running over a reliable
              protocol, and especially for testing relpkt so you can fuzz it and bypass the crc errors.

relpkt

       accepter = relpkt[(options)]
       connecting = relpkt[(options)]

       Converts an unreliable packet interface  (currently  only  UDP  and  msgdelim)  into  a  reliable  packet
       interface.  This lets you have a reliable connection over a serial port (with msgdelim) or UDP.

       Note that UDP is not recommended, it doesn't handle flow control and such in a friendly manner.

       relpkt is unusual in dealing with clients and servers.  The protocol is symmetric, for the most part, you
       can start two clients and they will connect to each other, if they are started relatively close  in  time
       to avoid one timing out.  A relpkt server will simply wait forever for an incoming connection on an open.

       relpkt does not support readbuf.  It supports the following:

       max_pktsize=<n>
              Sets  the  maximum  size  of  a  packet.  This may be reduced by the remote end, but will never be
              exceeded.  This must be at least 5 bytes shorter than the maximum packet  size  of  the  interface
              below  it.   This  defaults  to  123 (msgdelim max packet size - 5).  If run over UDP, this should
              probably be increased for performance.

       max_packets=<n>
              Sets the maximum number of outstanding packets.  This may be reduced by the remote end,  but  will
              never be exceeded.

       mode=client|server
              By  default  a  relpkt is a server on an accepter and a client on a connecter.  See the discussion
              above on clients and servers.

       timeout=<gtime>
              Specify the time for a timeout.  If relpkt sends a message requiring an ack,  it  will  wait  this
              long  before  resending the packet.  See the "gtime" section for more info on how to set the time.
              If you don't specify a time modifier, the default is in seconds.  The default is one second.

       max_timeouts=<n>
              The maximum number of timeouts before giving up on a connection.  The default is 5.

ratelimit

       accepter = ratelimit[(options)]
       connecting = ratelimit[(options)]

       Limit the transmit rate of data going through this filter gensio.  A number of bytes is let through, then
       transmit  is  delayed  until the given delay has passed.  Receive is not currently rate limited, but that
       may be added in the future.

       xmit_len=<n>
              The number of bytes to allow before a delay.  Note that the delay  occurs  after  a  single  write
              succeeds,  so  if  a  single  byte is written it will delay.  If a write is done of more than this
              length, it will be limited to this length.  Defaults to one.

       xmit_delay=<gtime>
              The amount of time to wait between writes.  See the "gtime" section for information for this  time
              specification.  This must be supplied.

trace

       accepter = trace[(options)]
       connecting = trace[(options)]

       A transparent gensio that allows the data passing through it to be sent to a file.  Useful for debugging.
       It can also block data in either direction.

       Note that the trace gensio only prints data that is accepted by the other end.  So, for instance, if  the
       trace  gensio receives 100 bytes of read data, it will deliver it immediately to the gensio above it.  If
       that only accepts 40 bytes, trace will only print 40 bytes and will only accept 40 bytes from the  gensio
       below it.  Same for sent data.

   Options
       trace does not support readbuf.  It supports the following options:

       dir=none|read|write|both
              Sets  what  data  is  traced.   "none"  means  no data is traced (the default), "read" traces data
              flowing up the gensio stack (read by the parent), write traces data flowing down the gensio  stack
              (written by the parent), and "both" traces reads and writes.

       block=none|read|write|both
              Blocks  data  in  one  or both directions.  "none" means data flows both directions (the default),
              "read" means data flowing up the gensio stack is discarded, write  means  data  flowing  down  the
              gensio  stack  is discarded, and "both" discards both reads and writes.  Data that is discarded is
              not traced.

       raw[=yes|no]
              If set, traced data will be written as raw bytes.  If not set, traced  data  will  be  written  in
              human-readable form.

       file=<filename>
              The  filename  to  write  trace  data to.  If not supplied, tracing is disabled.  Note that unless
              delold is specified, the file is opened append, so it will add new trace data onto the end  of  an
              existing file.

       stderr[=yes|no]
              Send the trace output to standard error.  Overrides file.

       stdout[=yes|no]
              Send the trace output to standard output.  Overrides file and stderr.

       delold[=yes|no]
              Delete the old data in the file instead of appending to the file.

perf

       accepter = perf[(options)]
       connecting = perf[(options)]

       A  gensio  for  measuring throughput for a connection.  This allows the performance of a connection to be
       measured.  It does not pass any data through.  Instead, it  writes  raw  data  to  the  lower  layer  (if
       write_len is set) and reads data from the lower layer, counting the bytes and measuring the time.

       To  the  upper  layer,  perf  prints out statistics about the data transfer.  It prints out the number of
       bytes written and read each second, and at the end it prints a total.

       If write_len and/or expect_len is non-zero, then the filter will return GE_REMCLOSE when it runs  out  of
       write  data  and  has received all expected data.  If both are zero, the connection will not be closed by
       the gensio.

   Options
       perf does not support readbuf.  It supports the following options:

       writebuf=<n>
              Sets the size of the buffer to write to the child gensio.  Each write will  be  this  size.   This
              defaults to zero.

       write_len=<n>
              The number of bytes to write.

       expect_len=<n>
              The number of bytes to expect from the other end.

conacc

       accepter = conacc[(options)],<gensio string>

       conacc  is  a gensio accepter that takes a gensio as a child.  When the accepter is started, it opens the
       child gensio.  When the child gensio finishes the open, it reports a new child  for  the  accepter.   The
       reported gensio can be used normally.

       When  the  gensio  is  closed,  when  the close completes the accepter will attempt to re-open the gensio
       immediately and will disable itself if the connect fails, unless retry-time is set.  This means  that  if
       the  gensio  has  some sort of random address (like a pty or a tcp address with the port set to zero) you
       can get a different address for the re-opened gensio.  So you must refetch the  local  address  or  local
       port in this case.

   Options
       The readbuf option is not accepted.

       retry-time=<gtime>
              Instead  of  restarting a closed connection immediately, this will cause a delay between the close
              and the re-open.  Also, if the connect fails, it will not disable itself,  it  will  wait  another
              retry-time  period  and try the connect again.  See the section on gtime above.  The unit defaults
              to milliseconds.  The default value is zero.

   Direct Allocation
       Allocated as a terminal gensio with gdata as a "const char *".  That is the specification of  the  gensio
       below it.

mdns

       connecting = mdns[(options)][,<name>]

       This  gensio  uses mDNS to find a service and then attempts to connect to it.  This can be convenient, it
       finds the connection type, address, and port for you, automatically  adds  telnet  and  rfc2217  if  it's
       available.  The mDNS name can be set as an option or as the string after the comma show above.

       The  name,  type,  host,  and  domain  strings can be wildcarded in various ways.  See "STRING VALUES FOR
       WATCHES" in gensio_mdns(3) for details.

   Options
       The readbuf option is accepted, but if it is not specified the default value for readbuf  will  be  taken
       for the sub-gensio is taken.  In addition to readbuf, the mdns gensio takes the following options:

       nostack[=true|false]
              By  default  the  mdns  gensio  will  attempt  to  use the "gensiostack" text string from the mDNS
              service.  If you don't want it to do this, setting this option will turn it off.

       ignore-v6-link-local[=true|false]
              Ignore IPv6 link local addresses, ones  starting  with  "fe80:".   They  cause  problems  on  some
              systems.

       mdnstimeout=<gtime>
              Set  the  amount of time to wait for mdns to find the item.  See the "gtime" section for more info
              on how to set the time.  The default unit is milliseconds, default time is 1 second.  The  default
              setting  for  mdnstimeout  is  not  a  gtime,  it is in integer in milliseconds.  You may also use
              "timeout" instead of "mdnstimeout", but not in the default.

       name=<mdnsstr>
              Set the mdns name to search for.  You generally want to set this, otherwise you will get the first
              thing that comes up from the search.

       type=<mdnsstr>
              Set the mdns type to search for.

       domain=<mdnsstr>
              Set the mdns domain to search for.  You generally don't use this.

       host=<mdnsstr>
              Set the mdns host to search for.  You generally don't use this.

       interface=<num>
              Set the network interface number to search on.  The default is -1, which means all interfaces.

       nettype=unspec|ipv4|ipv6
              The  network  type  to search for.  unspec means any type, otherwise you can choose to limit it to
              ipv4 and ipv6.

       nodelay[=true|false]
              Sets nodelay on the socket.  This will be ignored for udp.  Note that the default value  for  mdns
              is  ignored,  if you don't set it here it will take the default value for the sub-gensio that gets
              chosen.  laddr=<addr> An address specification to bind to on the local socket  to  set  the  local
              address.

   Direct Allocation
       Allocated  as a terminal gensio with gdata as a "const char *".  That is the specification of the mdns as
       a string.

kiss

       accepter = kiss[(options)]
       connecting = kiss[(options)]

       A gensio that implements the KISS amateur radio protocol for transferring data between a  TNC  and  AX25.
       See  http://www.ax25.net/kiss.aspx for details.  It contains a number of tunable parameters, you probably
       shouldn't mess with most of them.

       This is a normal packet-oriented interface.

       KISS supports multiple TNCs underneath it.  To write to a specific TNC, you must use the  auxdata  string
       "tnc:<n>"  when  writing.   If  you don't set that, the TNC is assumed to be zero.  On reading, "tnc:<n>"
       will always be in one of the auxdata fields.  You shouldn't set a TNC larger than the  configured  number
       of TNCs.

       There  is  a  8-bit protocol field in the AX25 frame call the PID.  This is not passed in the data, it is
       also in the auxdata with the format "pid:<n>".  And to set the pid, pass it in the auxdata on write.   If
       you don't set the pid, it defaults to 240 (0xf0).

   Options
       kiss supports the following options:

       readbuf=<n>
              Sets the maximum packet size that can be read from the TNC.  Defaults to 256.

       writebuf=<n>
              Sets the maximum packet size that can be written to the TNC.  Defaults to 256.

       tncs=<n>
              The number of supported TNCs.  Defaults to 1.

       server[=yes|no]
              Is  this  a KISS server or client.  A client will set the tunable parameters on the TNC.  A server
              is expected to be a TNC, but this isn't fully  implemented  yet  as  you  can't  get  the  tunable
              parameters.

       setupstr=<string>
              Send the given string at startup to set up the device.

       setup-delay=<n milliseconds>
              Wait  for  the  given  number  of  milliseconds  after  sending the setup string before continuing
              operation.

       d710[=yes|no]
              If set to yes or just "d710" is given, set the setupstr to a value for  the  Kenwood  D710  radio.
              This is the same as doing: setupstr='xflow on\rhbaud 1200\rkiss on\rrestart\r'

       d710-9600[=yes|no]
              If set to yes or just "d710-9600" is given, set the setupstr to a value for the Kenwood D710 radio
              at 9600 bps.  This is the same as doing: setupstr='xflow on\rhbaud 9600\rkiss on\rrestart\r'

       txdelay=<n>
              The KISS txdelay parameter, in milliseconds, rounded to the nearest power  of  ten.   The  maximum
              values is 2550.  Default is 50ms.

       persist=<n>
              The  KISS  "P" parameter, ranging from 0-255.  I don't know what this means, the spec isn't clear.
              You'll have to figure it out on your own.  Default is 63.

       slottime=<n>
              The KISS slot time parameter, in milliseconds, rounded to the nearest power of  10.   The  maximum
              value is 2550ms, the default is 100ms.

       fullduplex[=yes|no]
              Set's full duplex on the connection.

       sethardware=<n>
              A  hardware-specific  control value ranging from 0-255.  It's meaning depends on the hardware.  By
              default it is not set.

ax25

       accepter = ax25[(options)]
       connecting = ax25[(options)]

       A gensio that implements the AX25 amateur radio protocol for transferring data.  You would generally  run
       this on top of a KISS gensio.  See http://www.ax25.net for details.

       This is a normal packet-oriented interface.

       It  is  also a channel-based implementation.  Each AX25 connection to a remote system is implemented as a
       channel.  You can also have an unconnected channel if you want to just receive UI frames.

       There is no server/client setting on an ax25 gensio.  The protocol is symmetric, so it's  not  necessary.
       An  ax25 accepter will take the first connection that comes in and deliver it as a gensio, but after that
       there's really no difference.

       When running as an accepter, incoming connections will be delivered as new connections, not new channels.
       This  allows  you  to  use an ax25 gensio more naturally underneath a server without having to know about
       ax25 in the code.  For instance, to create a simple AX25 server that  reflects  all  incoming  data,  you
       could create a reflector:

              greflector -t kiss,tcp,1234

       then you could create the server:

              gensiot -i 'echo' --server -a \
                  'ax25(laddr=test-1),conacc,kiss,tcp,localhost,1234'

       then you could connect to it:

              gensiot 'ax25(laddr=test-2,addr="0,test-1,test-2"),kiss,tcp,localhost,1234'

       So  to  use  this, allocate an ax25 gensio.  If you want to make a connection, you must set the addr to a
       destination address.  By default the laddr will be set from the addr if the addr  is  supplied.   If  you
       just  want  UI  frames, you don't need to set an address (more on that later).  Then you open the gensio.
       An ax25 gensio without an address will just open immediately and start receiving UI packets as  directed.
       With an addr set, it will attempt to make a connection.  Once that is up (or fails), the open callback is
       called.

   AX25 Addresses
       A gensio AX25 address string is in the form:

              [ax25:]tncport,dest[:c|r],src[:c|r][,extra1[:h]
              [,extra2[:h][..]]]

       tncport is a number from 0-15 specifying which TNC to use.  dest and src and subaddresses specifying  the
       destination  and source addresses.  Note that the source address better match an laddr, or the connection
       won't work.  extra fields are also subaddresses.   These  are  used  for  routing  (a  function  that  is
       deprecated  and  no longer use) and by APRS for it's own purposes, see the APRS spec for details.  The c,
       r, and h values are bits in the address that you generally don't care about, except for the h  field  for
       APRS.

       Subaddresses are in the form

              callsign-n

       where callsign is a set of alphanumeric digits (a-zA-Z0-9) and n is a number 0-15.  Lower case digits are
       converted to upper case in the address and not converted back on receipt.

   Handling unconnected packets (UI frames)
       To receive UI frames, you must enable the GENSIO_CONTROL_ENABLE_OOB control on the gensio.   If  you  set
       the  value to 1, you will receive UI frames where the destination matches one of your laddrs.  If you set
       it to 2, you will receive all UI frames (promiscuous mode).  0 disables receipt of UI frames.

       UI frames are reported with the "oob" in the auxdata,  like  out  of  band  data.   Note  that  you  must
       completely handle all the UI frame in the call.  If you don't consume all the data, it will not be called
       again.

       You can have a channel that receives both connected data and UI frames, but you would  generally  have  a
       separate  channel  with  no  addr  set  for  receiving UI frames.  If you don't set the laddr field, that
       channel can only be used for promiscuous mode.

       On received packets, the auxdata will contain a field starting with "addr:" and the rest  is  the  gensio
       AX25  address  in  the  packet.   When  sending  a UI frame, you must set "oob" and "addr:" fields in the
       auxdata, with a valid address in the "addr:" field.

   Options
       Option values for channels are all inherited from the options used to create the  first  channel,  except
       for addr (which must be supplied for each channel if you care) and laddr (which is only used on the first
       channel.  ax25 supports the following options:

       readbuf=<n>
              Sets the maximum packet size that can be read.  Defaults to 256.

       writebuf=<n>
              Sets the maximum packet size that can be written.  Defaults to 256.

       readwindow=<n>
              Sets the maximum packet size that can be received and unacked.  Defaults to 7 for extended  and  4
              for non-extended.

       writewindow=<n>
              Sets the maximum number of packets that can be sent unacked to the remote side.  Defaults to 7 for
              extended and 4 for non-extended.

       extended=<n>
              Set the extended mode.  Setting it to 1 will enable 7-bit sequence numbers,  the  connection  will
              first  attempt  to  use 7-bit sequence number.  If that fails, it will fall back to 3-bit sequence
              numbers.

              Setting the value to 2 will enable a non-standard operation that will add parameter negotiation to
              the  connection  startup.   Setting  the  readbuf,  writebuf,  readwindow, and writewindow without
              extended=2 really isn't very useful as without the negotiation it will be forced to fall  back  to
              the defaults.  If extended=2 fails, it will fall back to extended=1.

       laddr=<subaddr>[;<subaddr[...]]
              Set  the  addresses the ax25 gensio will receive packets for.  Except for promiscuous UI mode, the
              destination of a packet must match one of these addresses to be handled.  This can only be set  on
              the accepter or on the first connection and applies to all channels.

              If you do not set this, but addr is set, the laddr will be set from the source address of addr.

       addr=<ax25addr>
              Set the address of the remote end of the connection.  Packets will be sent to this address.

       crc[=yes|no]
              Enable CRC checking.  Default is off.

       ign_emb_ua[=yes|no]
              Some  AX.25 stacks do not properly reset themselves when they get a second SABM (due to a timeout)
              but they still send a UA.  If you are getting errors about receiving a UA while connected and  the
              connection hangs, try enabling this option.

       srt=<n>
              The  initial  smoothed  round  trip  time  for  the connection, in milliseconds.  See the spec for
              details, you probably don't need to mess with it.  Note that this value you set here is multiplied
              by  the  number  of  digipeaters  between  the  source  and  the destination for the actual value.
              Defaults to 1500.

       t2=<n> The timer 2 value for the connection, in milliseconds.  See the spec  for  details,  you  probably
              don't need to mess with it.  Defaults to 2 seconds.

       t3=<n> The  timer  3  value  for the connection, in milliseconds.  See the spec for details, you probably
              don't need to mess with it.  Defaults to 300 seconds.

       retries=<n>
              Number of retries on a send before giving up and  dropping  the  connection.   See  the  spec  for
              details, you probably don't need to mess with it.  Defaults to 10.

xlt

       accepter = xlt[(options)]
       connecting = xlt[(options)]

       A  gensio that translates characters.  This is primarily for translating line feeds and carraige returns,
       but may eventually be extended to do string substitutions and such.

       The readbuf option is not available in this gensio.

   Options
       in=<n>:<m>
              Translate character n (a number, 0xnn for hex, 0nnn  for octal, or nn for decimal) to character  m
              on data read from the gensio.

       out=<n>:<m>
              Like in, but translate character n to character m on data written to the gensio.

       nlcr   Translate  new lines to carraige returns on data read from the gensio, and carraige returns to new
              lines on data written to the gensio.

       crnl   Translate carraige returns to new lines on data read from the gensio, and new  lines  to  carraige
              returns on data written to the gensio.

keepopen

       connecting = keepopen[(options)]

       A  filter  gensio  that  makes  it  appear to the user that the gensios below it are always open.  If the
       gensio below it goes away, this will attempt to re-open it periodically.

       The readbuf option is not available in this gensio.

   Options
       retry-time=<gtime>
              Set the retry interval.  See the section on gtime for detail on this.  Defaults to milliseconds it
              no unit given.  The default is 1 second.

       discard-badwrites[=yes|no]
              Normally  this gensio will flow-control the upper layer when the lower gensio is not open.  If you
              enable this, it will just throw write data away if the lower gensio is not open.

script

       connecting = script[(options)] accepting = script[(options)]

       A filter gensio that allows an external program to interact with the child gensio before  reporting  that
       it  is  open.   The external program runs with its stdio connected to the child of this gensio, so writes
       from the external program get written to the child and reads from the child get written to  the  external
       program's  stdin.   If  the  program  returns  without  error, the open for this gensio succeeds.  If the
       program returns an error, GE_LOCALCLOSED is reported as an open error.

       The readbuf option is not available in this gensio.

   Options
       script=<string>
              Run the program given in the string as  the  external  program.   This  is  equivalent  to  doing:
              gensio=stdio(noredir-stderr),<string>, it just a shortcut.

       gensio=<string>
              Instead  of running a program, run the given gensio.  When the gensio closes, handle an error.  If
              the gensio supported getting an error code, that is done.

sound

       connecting = sound[(options)],<device>

       The sound gensio provides access to sound devices on the  platform.   It's  an  unusual  gensio  in  many
       respects.  It's not terribly useful for normal streaming operation.  It is a streaming operation, though,
       so it still fits.  But to avoid underruns and overruns, the stream has to  be  continuously  supplied  or
       consumed.

       The  stream  consists of bytes of binary data in the host's byte order.  If the low-level sound interface
       uses a different byte order, it is converted to the host's order in the  gensio.   The  gensio  can  also
       convert  data  types.   If  you ask for a float format and the low level driver can only do integers, the
       gensio will convert for you.  Each data item (byte, int16, etc) is called a sample.  So the driver has  a
       user format (what the user sees) and a PCM format (what the driver uses).

       A  stream  has  a  number  of  channels,  at least one.  Stereo, for instance, has two channels.  A frame
       consists of samples for all channels.  Frames are always interleaved; the individual channels  appear  as
       successive  data  items in the stream.  So in stereo, sample1 is channel 1 in the first frame, sample2 is
       channel 2 in the first frame, sample 3 is channel 1 in the second frame, etc.

       A buffer is a set of frames.  A buffers's size is specified in  frames,  not  bytes.   Reads  are  always
       provided  in  buffer  size  chunks.  If you do not comsume all the data in a buffer, it will give you the
       rest of the buffer the next read, until the buffer is consumed.  Writes can be written in any  size,  but
       it's generally most efficient to always write buffer sized chunks.

       A  number  of  buffers  can also be specified.  You generally want a large enough number that data can be
       smoothly written into the device without delay if the program lags a bit, but too large and  you  end  up
       with lag if you want to change the data being written..

       A  sound  gensio  may  have  input, output, or both.  You specify which you want by setting the number of
       channels to a non-zero value.  Most of the parameters can be prefixed with "in" or "out" to specify  that
       the  parameter only applies to the input and output device.  If you don't have that prefix, it will apply
       to both the input and output.  Note that the input and output streams are  completely  independent;  they
       can have different type, format, rates, etc.

       Different  sound  interfaces  are  available  on  platforms.   For  Linux,  alsa  and file interfaces are
       available, and possibly portaudio, depending on how it is compiled.  On Windows, win and file  interfaces
       are available and possibly portaudio.  On Macos portaudio and file are available.

       The  device  is  specified  on  the command line.  The name is system-dependent.  For alsa, the name must
       match exactly.  You can use "aplay -L" or "arecord -L" to list input and output  devices  available.   Or
       you can use the "gsound -L" program.

       For  Windows  and  portaudio, the name just has to match part of the device's name.  Windows names always
       start with a number.  So, for instance, if the output of "gsound -L" on your windows platform is:

                  0:Microphone (Realtek(R) Audio)     input,inchans=2
                  0:Speakers (Realtek(R) Audio)       output,outchans=2

       The numbers at the beginning are subject to change,  so  it's  better  to  use  part  of  the  name  like
       "Realtek", which will match both input and output.  It will not select an output-only device for input or
       an input-only device for output.

       On MacOS with portaudio you might see:

                  0:USB Audio CODEC   output,outchans=2
                  1:USB Audio CODEC   input,inchans=2
                  2:Mac mini Speakers output,outchans=2 where you could use "USB Audio" for the name.

              For file type, the device name is a filename; data is streamed to/from the file in the PCM format.
              If the filename is "-", then stdio is used instead of opening a file.

              The readbuf option is not available in this gensio, obviously.

   Options
       <samplerate>-<channels>-<format>
              For  simple  applications,  the  sound  gensio takes a compact and simple format as an option.  It
              specifies  those  things  for  both  the  input   and   output   channel.    So,   for   instance,
              "sound(44100-2-float)" would be CD-rate two channel using floating point numbers.

       list[=yes|no]
              Instead of opening a sound device, the gensio will provide data about the various sound interfaces
              available.  Every other option but "type" is ignored.  If "type" is supplied, list the  interfaces
              for that type.  If "type" is not supplied, list the interfaces for the default one.

              The data will be a string with each interfaces separated by a newline.  There will be an interface
              name, a tab, and the interface specification.

       outdev=<str>
              If the output device has a different name than the input device, it must be specified separately.

       inbufsize=<n>, outbufsize=<n>, bufsize=<n>
              Specify the buffer size, in samples.  This defaults to 1024.

       innbufs=<n>, outnbufs=<n>, nbufs=<n>
              Specify the number of buffers to use.  This may or may not be  used  depending  on  the  interface
              type.  It's ignored for file, for instance.  Defaults to 100.

       chans=<n>, inchans=<n>, outchans=<n>
              Set  the number of input and output channels.  One of these must be specified, if you say chans it
              will set both the input and output number of channels.  If you only specify in or out,  the  other
              is not enabled.

       inrate=<n>, outrate=<n>, rate=<n>
              The sample rate, in samples per second.  Common ones are 44100 (CD), 48000 (DAT).

       intype=<n>, outtype=<n>, type=<n>
              Set  the  interface  type.  Must be "alsa" (Linux only), "win" (Windows only), "portaudio" (MacOS,
              generally) or "file".  If not set, this default to alsa on Linux, win on Windows, and portaudio no
              Macos.

       informat=<n>, outformat=<n>, format=<n>
              Set the type of data to supply to the user.  This is one of: float64, float, s32, s32, s16, or s8.
              User samples are always signed and either floating point or integer.  Floating point is normalized
              from -1.0 to 1.0.  You must specify this.

       inpformat=<n>, outpformat=<n>, pformat=<n>
              The  data  format on the PCM size.  You have all the data formats specified for format above.  The
              integer ones can be prefixed with "u" instead of "s" to make them unsigned (like u16), and all may
              be  suffixed with "le" or "be" to make them little or big endian (like float64_le).  If you do not
              specify this, the gensio will attempt the same format as the user format.  If that  doesn't  work,
              it will attempt to pick the best matching format and convert.

afskmdm

       connecting = afskmcm[(options)]

       A  filter  gensio  that  sits  on  top of the sound gensio and implements an Audio Frequency Shift Keying
       modem, like is used on AX.25 amateur radio.  It must sit on top of a sound gensio.  Or, more accurately a
       gensio      that      implements      the      GENSIO_CONTROL_IN_BUFSIZE,     GENSIO_CONTROL_OUT_BUFSIZE,
       GENSIO_CONTROL_IN_FORMAT, and GENSIO_CONTROL_OUT_FORMAT controls.

       Note that the sound gensio must supply a float user format.

   Keying the Transmitter
       By default, afskmcm will not do anything specific to turn the transmitter on and off. In  this  case  the
       keying must be VOX, like a SignaLink.

       If  you  need  some other way to key the transmitter, afskmcm provide a key option.  This create a gensio
       that is used to turn the transmitter on and off.  Different types of keying options exist,  specified  by
       keytype.

       If  keytype  is  rw, which is the default, then it will open the key gensio and send the keyon string and
       the keyoff string for this purpose.

       If keytype is one of rts, rtsinv, dts, dtsinv then it will open the key gensio as a serial device and set
       the  RTS/DTR  lines  appropriately.   The "inv" options mean that setting the line "on" will turn off the
       transmitter, setting it "off" will enable the transmitter.

       You could do

              keytype=rts,key="serialdev,/dev/serial/by-path/pci-0000:00:14.0-usb-0:4.4.2.4.2:1.0-port0"

       to set up an RTS-base serial control on a port.

       There is a cm108 soundcard GPIO gensio available.  See that gensio for details, but you  would  generally
       do something like:

              keytype=cm108

       and  this  gensio will fetch the sound card identifier from the sound device and use the cm108gpio gensio
       to key the device.  If you have some special setup where the default won't work, you can use

              keytype=rw,key="cm108gpio,<dev>"

       See the cm108gpio gensio docs for details.

       If you need something more sophisicated, you could create your own program to do the keying and add:

              key="stdio,mykeyprog --parm1 --parm2",keyon="1",keyoff="0"

       to your afskmdm option and it would run the mykeyprog program when opened.  When it needed  to  transmit,
       it  would  write  a "1" (no newline or anything sent) to the stdin of the program.  When the transmission
       was complete, it would write a "0".  Not numbers, these are "0" and "1" characters.

       If you program sends output to stderr, you probably want to add stderr-to-stdout  to  the  stdin  so  the
       stderr buffers doesn't fill up and block the program.  Then stderr data will be ignored.

       You can use rigctld with this.  I have the following rigctld setup on my system:

              rigctld -m 1022 -r /dev/ttyUSB0 -s 4800 -P CM108 -p /dev/hidraw1

       And I use the following in my configuration:

              afskmdm(key="tcp,localhost,4532",keyon="T 1\n",keyoff="T 0\n")

       You  have  to  be careful of the quoting here, as the key specification must be in quotes because it will
       have commas.  Notice the use of "\n" in the strings for a new line.  Normal C "\"  escape  sequences  are
       handled.  Also, since the defaults for keyon and keyoff are what's given above, you don't have to specify
       those here.

       Anything read in from the key gensio is ignored.

   Options
       readbuf=<n>
              Sets the maximum packet size that can be read.  Defaults to 256.

       writebuf=<n>
              Sets the maximum packet size that can be written.  Defaults to 256.

       nchans=<n>, in_nchans=<n>, out_nchans=<n>
              Specify how many channels are coming from/going to the sound gensio.  The sound gensio interleaves
              the sound for multiple channels.  By default this is fetched from the sound gensio.

       chan=<n>, in_chan=<n>, out_chan=<n>
              Which  specific  channel  to  use.   One one channel is used for input sound and output sound, the
              others are ignored or filled with zeros.  By default this is zero.

       out_chans=<n>
              Specify a bitmask of which channels to output sound on.  The same sound will  be  output  for  all
              selected channel.  So n=1 will only output on channel 0, n=3 will output on channels 0 and 1, etc.
              By default only channel 0 is output on.

       samplerate=<n>, in_samplerate=<n>, out_samplerate=<n>
              The sample rate, samples per second, of the data.  By default  this  is  fetched  from  the  sound
              gensio.

       checkax25[=true|false]
              Check  that  the  packet  is  a  valid  AX.25  packet,  that it has valid AX25 length and address.
              Normally the AX.25 layer does this, but this can be used when testing without an  AX.25  layer  to
              reject  bad  packets.   Default to false.  Note that if you set crc to false, this option will not
              work.

       crc[=true|false]
              Check and send CRCs on packets.  Normally you want the afskmdm code to do this, but can be  useful
              for testing.  Default to true.

       wmsgs=<n>
              The number of working messages at the same time.  If the bit fails the certainty test (see below),
              for every current working message, two are created, one with each bit possibility, up to the count
              specified  in this option.  These are kept until a message is correctly received (with CRC) or the
              series of bits is not valid.

              This way, if wmsg is 2^n, a message can be correctly decoded if up to n bits are wrong.   So  it's
              sort of an error correction code without a code.  Defaults to 32.

       wmsg-extra=<n>
              Sets  the  number of extra amplification levels for the mark and space frequencies to try.  If set
              to 1, an extra complete detection is done with the space frequency amplified by 3db, then the mark
              frequency  amplified  by 3db.  If set to 2, it will do this with3db then 6db, and so on.  This can
              help compensate for filtering on the different frequencies.  Defaults to 1.

       min-certainty=<float>
              A floating point number that specifies the minimum certainty above which a bit is considered good.
              The  ratio  of the signal power for the mark and space frequencies is calculated as the certainty.
              If that certainty is below min-certainty, it does the wmsgs procedure above.  Defaults to 2.0.

       filttype=[fir|iir|none]
              A 2nd-order low-pass Butterworth IIR filter or a low-pass FIR filter is implemented on the  input.
              This selects which filter, or no filter.  The IIR filter doesn't use very much CPU, the FIR filter
              uses a lot of CPU at higher sample rates.  This is mostly for experimentation.  The default is IIR
              for sample rates above 30000Hz and FIR for lower sample rates.  Lower sample rates don't work well
              with the IIR filter, but there's not much difference at higher sample rates.

       lpcutoff=<n>
              This sets the cutoff frequency for the input filter.  Setting it to zero disables it.  The default
              is 2500Hz.

       trfreq=<n>
              This  sets the transition frequency width for the FIR filter.  This is ignored for the IIR filter.
              The default is 500Hz.  Smaller numbers make a sharper cutoff but result in more CPU being used.

       tx-preamble=<n>
              The time in milliseconds at the beginning of a message that is just flags.  This lets the receiver
              turn on and the other end synchronize.  Default is 300.

       tx-tail=<n>
              The time in milliseconds at the end of the message that is just flags.  Default is 100.

       tx-predelay=<n>
              The amount of time to wait after another sender has finished sending a message before the transmit
              is started.  Default is 500ms.

       volume=<float>
              Sets the transmit volume, from 0.0-1.0.  Values above 1.0 will clip.  Default is .75.

       key=<gensio string>

       This creates a gensio that will be used to key the transmitter on and
              off.  See the discussion above on keying for more details.  keytype=rw|rts|rtsinv|dtr|dtrinv|cm108
              This  sets  the  type  of  keying  done,  per  the  discussion  above.   This  is  rw  by default.
              keyon=<string>, keyoff=<string>

       The strings to send to the key gensio to turn the transmitter on and
              off.  For keytype=rw only.  The default to "T 10 and "T 00  by  default,  which  is  what  rigctld
              takes.  keybit=<n>

       This sets the bit number to use on the cm108 keytype.  This is 3 by
              default.  full-duplex[=yes|no]

       Treat the read and write streams as completely independent.  Transmit
              does not check if something is being received before sending, all sends just start immediately.

cm108gpio

       connecting = cm108gpio[(options)],<soundcard>

       This allows a GPIO on a cm108 soundcard to be controlled.  Some radio sound card devices use one of these
       bits to key the transmitter.  Any write with a '1' in it will enable the GPIO, any write with a '0' in it
       will disable the GPIO.  There are 8 available GPIOs, ranging 1-8, most devices use 3.

       For  Linux,  <soundcard> is the soundcard number or device name given to open the sound device, generally
       what's right after the ":", like "plughw,1,0" would be "1".  If it was  "plughw,Device,0",  it  would  be
       "Device".

       For  Windows,  <soundcard> is the same thing you put for the soundcard, like "USB PnP Sound", or whatever
       "gsound -L" returns for your device.

       The readbuf option is not available in this gensio.

   Options
       bit=1-8
              The bit number to control.  The default is 3.

Forking and gensios

       Unlike normal file descriptors, when you fork with a gensio, you now have two unassociated copies of  the
       gensios.   So  if you do operations on one, it might mess up the other.  Even a close might cause issues,
       if you close an SSL connection, it sends data to the other end to close the connection, even if the other
       fork doesn't want that.

       To  avoid  issues  with  this,  you should generally first make sure that no thread is in a wait, service
       call, or any type of thing that would examine file descriptors or timers and act on them.  This  is  very
       important, and you must do it before you fork.

       Then after you fork, you should call:

              gensio_disable(io)

       on  all  the gensios that fork is not using, then free the gensios.  Don't use close, use free.  Then you
       should call:

              gensio_acc_disable(acc)

       on every gensio accepter that fork is not using, then free them.  If a connection is in progress and  has
       not been reported to the user, it will be disabled then closed.

       You  cannot  share a gensio between two different processes.  If a gensio is used in one fork, it must be
       disabled and closed in the other fork.

       Another issue with forking on Linux is epoll.  An epoll fd is not duplicated on a fork,  both  forks  get
       the  same epoll fd.  If you close the epoll fd in one for, it will close it for the other.  To avoid this
       issue, the os handler has a handle_fork() function that you must call after a fork in the new  fork  (not
       the  old  one).   It  will  handle  any cleanup required after the fork.  Other systems may require other
       cleanups after a fork, so you should always call this after a fork.

SEE ALSO

       gensiot(1), sctp(7), udp(7), tcp(7), unix(7)

KNOWN PROBLEMS

       None.

AUTHOR

       Corey Minyard <minyard@acm.org>