jammy (5) gensio.5.gz

Provided by: libgensio-dev_2.3.5-1build2_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.  Particularly, you must set the max read and write size to the same value, and you must accept
       all data on receipt and write complete packets all at once.

       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 remaning 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 othersize 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.  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.  This is the default.

       In general IPv6 addresses are preferred if both are available.

       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.  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.

TCP

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

       A TCP connecting gensio  must  have  the  hostname  specified.   Mulitiple  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 overriden 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.

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.

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.

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.

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 work on (except for wronly).

       This is, no surprise, a serial gensio.

       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:

       nouucplock[=true|false]
              disables UUCP locking on the device.  Useful for /dev/tty, which shouldn't use locking.   This  is
              not available as a default.

       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.

       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]
              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.

       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 to not  lower
              the  modem  control  lines  on close (false).  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.

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 uid and guid to the current set
       effective uid and guid if the effective and real uids are  different.   This  way  a  user  can  set  the
       effective  uid  and  gid  to  what  they  want  the program to run under, but keep the 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 effective 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.

       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.

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.

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

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.

       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>])".

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.

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.

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.

       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.

       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.

       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.

       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.

       In  the  forked process, the pty code will set the uid and guid to the current set effective uid and guid
       if the effective and real uids are different.  This way a user can set the effective uid and gid to  what
       the  want to pty to run under, but keep the real 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  effective
       userid is in.  Note that nothing is done if the effective and real userids are the same.

       The pty gensio supports the GENSIO_CONTROL_ENVIRONMENT control to allow the environment to be set for the
       new process.

       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.

       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.

       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.

   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.

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.

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,<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.
       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.

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 andport 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.

   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.

       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.

       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>