1187938Semax /*
2187938Semax  * This part for NCR UNIX with is from Andrew Maffei (arm@aqua.whoi.edu). It
3187938Semax  * assumes TLI throughout. In order to look up endpoint address information
4187938Semax  * we must talk to the "timod" streams module. For some reason "timod" wants
5187938Semax  * to sit directly on top of the device driver. Therefore we pop off all
6187938Semax  * streams modules except the driver, install the "timod" module so that we
7187938Semax  * can figure out network addresses, and then restore the original state.
8187938Semax  */
9187938Semax
10187938Semax#ifndef lint
11187938Semaxstatic char sccsid[] = "@(#) ncr.c 1.1 94/12/28 17:42:34";
12187938Semax#endif
13187938Semax
14187938Semax#include <sys/types.h>
15187938Semax#include <stdio.h>
16187938Semax#include <syslog.h>
17187938Semax#include <sys/tiuser.h>
18187938Semax#include <stropts.h>
19187938Semax#include <sys/conf.h>
20187938Semax
21187938Semax#include "tcpd.h"
22187938Semax
23187938Semax#define MAX_MODULE_COUNT	10	/* XXX */
24187938Semax
25187938Semax/* fromhost - tear down the streams stack then rebuild it */
26187938Semax
27187938Semaxvoid    fromhost(struct request_info *request)
28187938Semax{
29187938Semax    int     i;
30187938Semax    int     num_mod;
31187938Semax    struct str_list str_list;
32187938Semax    struct str_mlist mod_buffer[MAX_MODULE_COUNT];
33187938Semax    int     fd = request->fd;
34187938Semax
35187938Semax    str_list.sl_nmods = MAX_MODULE_COUNT;
36187938Semax    str_list.sl_modlist = &mod_buffer[0];
37187938Semax
38187938Semax    /*
39187938Semax     * On systems with WIN streams support we have to be careful about what
40187938Semax     * is on the stream we are passed. This code POPs off all modules above
41187938Semax     * the pseudo driver, pushes timod, gets the host address information,
42187938Semax     * pops timod and then pushes all modules back on the stream.
43187938Semax     *
44187938Semax     * Some state may be lost in this process. /usr/etc/tlid seems to do special
45187938Semax     * things to the stream depending on the TCP port being serviced. (not a
46187938Semax     * very nice thing to do!). It is unclear what to do if this code breaks
47187938Semax     * - the stream may be left in an unknown condition.
48187938Semax     */
49187938Semax    if ((num_mod = ioctl(fd, I_LIST, NULL)) < 0)
50187938Semax	tcpd_warn("fromhost: LIST failed: %m");
51187938Semax    if (ioctl(fd, I_LIST, &str_list) < 0)
52187938Semax	tcpd_warn("fromhost: LIST failed: %m");
53187938Semax
54187938Semax    /*
55187938Semax     * POP stream modules except for the driver.
56187938Semax     */
57188013Semax    for (i = 0; i < num_mod - 1; i++)
58188013Semax	if (ioctl(fd, I_POP, 0) < 0)
59187938Semax	    tcpd_warn("fromhost: POP %s: %m", mod_buffer[i].l_name);
60187938Semax
61187938Semax    /*
62187938Semax     * PUSH timod so that host address ioctls can be executed.
63187938Semax     */
64187938Semax    if (ioctl(fd, I_PUSH, "timod") < 0)
65187938Semax	tcpd_warn("fromhost: PUSH timod: %m");
66187938Semax    tli_host(request);
67187938Semax
68299826Spfg    /*
69187938Semax     * POP timod, we're done with it now.
70187938Semax     */
71187938Semax    if (ioctl(fd, I_POP, 0) < 0)
72187938Semax	tcpd_warn("fromhost: POP timod: %m");
73187938Semax
74187938Semax    /*
75187938Semax     * Restore stream modules.
76187938Semax     */
77187938Semax    for (i = num_mod - 2; i >= 0; i--)
78187938Semax	if (ioctl(fd, I_PUSH, mod_buffer[i].l_name) < 0)
79187938Semax	    tcpd_warn("fromhost: PUSH %s: %m", mod_buffer[i].l_name);
80187938Semax}
81187938Semax