modemd(8)

NAME
modemd - incoming modem line control daemon

SYNOPSIS
modemd [modemcap-entry] tty-name

DESCRIPTION
Modemd is intended to be run by init(8) for each tty line on a given computer system that is connected to a modem. Each instance of modemd(8) initializes its modem to a known state, runs ttyaction(3) on the line with the action ``modemd'', user ``root'' and then waits either for the modem to report that the telephone line to which it is attached is ringing, or for some process which understands uucico-style tty locking to take the modem for its own use.

In the latter case, it waits for that program to release the modem line and then exits, allowing init(8) to restart it.

In the former case, modemd(8) waits for a CONNECT string to be output by the modem, and then connects the modem to whatever process or IP port was specified for that modem in the modemcap(5) file.

The modemcap-entry argument specifies the name of an entry in modemcap(5) which is to be used to determine how to communicate with the modem, how to initialize it, and what to do when a connection is established. If the modemcap-entry argument is omitted, a modemcap(5) entry with the same name as tty-name is used.

The tty-name must be specified, and names the terminal line to which the modem is connected. It should not contain a /dev/ prefix - this is added automatically by modemd.

These arguments are intended for compatibility with init, which normally invokes its terminal control programs with whatever arguments are specified in the ttys(5) entry for that terminal, followed by the name of the terminal. A typical ttys(5) entry for modemd(8) might look something like this:

        ttyA00 "/usr/libexec/modemd mt-2834-ppp" unknown on

INITIALIZATION
When modemd(8) is first started, it attempts to acquire a lock on the tty line compatible with uucico(8). If this succeeds, it initializes the tty to raw mode and disables canonical (line-at-a-time) input. If requested through the `zm' flag in modemcap(5), it then tries to reset the modem by dropping DTR for one second. In any case, it then attempts to minimally initialize the modem into a state in which it can converse. First, it sends the `+++' sequence, in case the modem is not in command mode. It then pauses for a second and sends `ATE1Q0V1H0', which turns on echoing, enables printing of result codes, turns on verbose result codes (e.g., `OK' and `CONNECT') and hangs up the modem.

Modemd(8) then tests to see if the modem is actually in a state in which it can be understood by sending `AT' by itself and waiting for the modem to output `OK'. If the modem doesn't respond, modemd(8) tries to reset it a second time, and if that fails, it gives up and reports that the modem is not responding.

Assuming that the modem has been successfully reset, modemd(8) then initializes it with the initialization string (see the `is' string in modemcap(5) for details on how to set up an initialization string and what it should look like).

If an error occurs while sending the initialization string, modemd attempts to isolate the error to a specific command in the string and report the bad command. If no error occurs, the modem is assumed to be in a known state after initialization.

WAITING FOR A CALL
Once the modem has been successfully initialized, modemd(8) releases its lock on the modem and waits for output from the modem. When it sees output, it attempts to reacquire its lock on the modem. If that fails, some other process is using the modem, so modemd(8) waits for the lock to be released and then exits. This allows init to restart modemd(8) so that the modem can be reinitialized.

If modemd(8) succeeds in reacquiring its lock on the modem, it waits for the modem to output `RING', indicating that the telephone line to which it is connected is ringing. Once the modem has output `RING', modemd(8) sends `ATA', which tells the modem to answer the phone and attempt to connect to a modem on the other end.

ANSWERING A CALL
Modemd(8) then waits for the modem to print either ``CONNECT'' or ``NO CARRIER''. If it prints the latter message, modemd(8) logs a message indicating that the connect didn't happen and exits, allowing init to restart the process. If the modem prints ``CONNECT'', modemd either connects the modem to a TCP/IP address specified in the `ca' and `cp' strings in modemcap(5), or starts up a process and connects its standard input, output and error descriptors to the modem. The program to be run may optionally be specified with the `lp' string in modemcap(5) — by default, login(1) is started. In addition, the `dl' flag can be used to indicate that modemd should perform the login process itself before starting up the user-specified program. See modemcap(5) for more details on how this works.

For compatibility with programs expecting to be run as a login shell, modemd(8) sets argv[0] to the login name preceded by dash.

SECURITY
If the usual login authentication process is to be skipped, it is important that a username be specified under whose uid and gid the process will run. By default, processes are run with uid and gid associated with the `nobody' username.

Skipping the authentication phase on login can be dangerous in surprising ways, and should always be approached with the utmost care. For example, it might make sense to have the login program be an invocation of telnet(1) connecting to another machine and relying on that machine's login security. However, by default, many versions of telnet(1) have commands which can be used to escape to a telnet prompt, and from there to a shell prompt.

Whether telnet(1) is invoked as a root process or as user `nobody', this could be a catastrophic security exposure.

Fortunately, recent versions of telnet allow the invoker to disable the escape character with the -E flag. Many programs which might potentially open up similar exposures have similar ways of preventing the exposure.

Awareness of this potential exposure and a careful investigation of any commands being invoked through modemd(8) without authentication can prevent an embarrassing and potentially expensive security hole from being left open.

DIAGNOSTICS
Modemd(8) logs all diagnostic and status messages via syslog(3), using the LOG_DAEMON facility code.

MESSAGES

It would be impractical to list all the possible messages that modemd(8) can log, but for troubleshooting purposes, more detailed explanations of some messages whose implications may not be obvious are included here.

Can't get modem's attention on command.
    Command was sent to the modem, and the modem didn't respond after a reasonable amount of time. This can mean that the command put the modem into a state that modemd can't deal with, or it can mean that the modem simply isn't responding for some other reason, for example a bad cable connection or a bad initial modem state.

Modem rejects command.
    The modem responded to command with ERROR, which means that it couldn't understand command. This generally means that the command is bad, but can also mean that the command is being sent too quickly for the modem to handle it. If the command doesn't fail when you type it to the modem, it could well be the latter. Try setting the `sm' flag in modemcap(5) if this happens. If you find a modem for which setting the sm flag allows the modem to be initialized, please notify the author of this program.

Timeout waiting for OK after command.
    The modem didn't respond after command was sent to it. This generally means that command has put the modem into a state where it won't respond with verbose result codes (or any result codes) following a command string, or that the command caused the modem to do something that takes a while (e.g., dialing out). If command is removed from the initialization string, the problem should go away.

Modem rejected ganged commands; try reducing bs#.
    The modem was unable to handle multiple initialization commands at once, but was able to deal with the commands when they were sent one at a time. This means that the modem buffer size as specified by the bs# value in modemcap(5) is too large. Its default value is 40, which should work with any Hayes-compatible modem. If you find a modem for which the default value of 40 doesn't work but some smaller value does, please notify the author of this program.

Can't get group id of uucp!
    Modemd(8) normally sets the terminals that it is managing to be owned by uucp so that programs such as uucico(8), tip(1) and cu(1) can access the modem. If the `uucp' user is not present in passwd(5), modemd(8) can't set the owner, and it will not be possible to share the modem line.

FILES
/etc/modemcap
    definitions which control the operation of modemd(8) and mpoold(8).
/var/spool/lock/LCK..ttyname
    lock files compatible with uucico(8).
/dev
    assumed to contain all tty devices.

SEE ALSO
modemcap(5), mpoold(8), tip(1), uucico(8), getty(8), login(8).

AUTHOR
Modemcap(5), modemd(8), and mpoold(8) were written for RadioMail Corporation by Ted Lemon <mellon@vix.com> under a contract with Vixie Enterprises, and are collectively based on mgetty, a version of getty written by Paul Vixie <paul@vix.com> which understands how to talk to Hayes-compatible modems. Many of Paul's ideas for enhancements to mgetty are incorporated here, along with some of my own.