1 /*
2  * This part for NCR UNIX with is from Andrew Maffei (arm@aqua.whoi.edu). It
3  * assumes TLI throughout. In order to look up endpoint address information
4  * we must talk to the "timod" streams module. For some reason "timod" wants
5  * to sit directly on top of the device driver. Therefore we pop off all
6  * streams modules except the driver, install the "timod" module so that we
7  * can figure out network addresses, and then restore the original state.
8  */
9
10#ifndef lint
11static char sccsid[] = "@(#) ncr.c 1.1 94/12/28 17:42:34";
12#endif
13
14#include <sys/types.h>
15#include <stdio.h>
16#include <syslog.h>
17#include <sys/tiuser.h>
18#include <stropts.h>
19#include <sys/conf.h>
20
21#include "tcpd.h"
22
23#define MAX_MODULE_COUNT	10	/* XXX */
24
25/* fromhost - tear down the streams stack then rebuild it */
26
27void    fromhost(request)
28struct request_info *request;
29{
30    int     i;
31    int     num_mod;
32    struct str_list str_list;
33    struct str_mlist mod_buffer[MAX_MODULE_COUNT];
34    int     fd = request->fd;
35
36    str_list.sl_nmods = MAX_MODULE_COUNT;
37    str_list.sl_modlist = &mod_buffer[0];
38
39    /*
40     * On systems with WIN streams support we have to be careful about what
41     * is on the stream we are passed. This code POPs off all modules above
42     * the pseudo driver, pushes timod, gets the host address information,
43     * pops timod and then pushes all modules back on the stream.
44     *
45     * Some state may be lost in this process. /usr/etc/tlid seems to do special
46     * things to the stream depending on the TCP port being serviced. (not a
47     * very nice thing to do!). It is unclear what to do if this code breaks
48     * - the stream may be left in an unknown condition.
49     */
50    if ((num_mod = ioctl(fd, I_LIST, NULL)) < 0)
51	tcpd_warn("fromhost: LIST failed: %m");
52    if (ioctl(fd, I_LIST, &str_list) < 0)
53	tcpd_warn("fromhost: LIST failed: %m");
54
55    /*
56     * POP stream modules except for the driver.
57     */
58    for (i = 0; i < num_mod - 1; i++)
59	if (ioctl(fd, I_POP, 0) < 0)
60	    tcpd_warn("fromhost: POP %s: %m", mod_buffer[i].l_name);
61
62    /*
63     * PUSH timod so that host address ioctls can be executed.
64     */
65    if (ioctl(fd, I_PUSH, "timod") < 0)
66	tcpd_warn("fromhost: PUSH timod: %m");
67    tli_host(request);
68
69    /*
70     * POP timod, we're done with it now.
71     */
72    if (ioctl(fd, I_POP, 0) < 0)
73	tcpd_warn("fromhost: POP timod: %m");
74
75    /*
76     * Restore stream modules.
77     */
78    for (i = num_mod - 2; i >= 0; i--)
79	if (ioctl(fd, I_PUSH, mod_buffer[i].l_name) < 0)
80	    tcpd_warn("fromhost: PUSH %s: %m", mod_buffer[i].l_name);
81}
82