144743Smarkm /* 244743Smarkm * This part for NCR UNIX with is from Andrew Maffei (arm@aqua.whoi.edu). It 344743Smarkm * assumes TLI throughout. In order to look up endpoint address information 444743Smarkm * we must talk to the "timod" streams module. For some reason "timod" wants 544743Smarkm * to sit directly on top of the device driver. Therefore we pop off all 644743Smarkm * streams modules except the driver, install the "timod" module so that we 744743Smarkm * can figure out network addresses, and then restore the original state. 844743Smarkm */ 944743Smarkm 1044743Smarkm#ifndef lint 1144743Smarkmstatic char sccsid[] = "@(#) ncr.c 1.1 94/12/28 17:42:34"; 1244743Smarkm#endif 1344743Smarkm 1444743Smarkm#include <sys/types.h> 1544743Smarkm#include <stdio.h> 1644743Smarkm#include <syslog.h> 1744743Smarkm#include <sys/tiuser.h> 1844743Smarkm#include <stropts.h> 1944743Smarkm#include <sys/conf.h> 2044743Smarkm 2144743Smarkm#include "tcpd.h" 2244743Smarkm 2344743Smarkm#define MAX_MODULE_COUNT 10 /* XXX */ 2444743Smarkm 2544743Smarkm/* fromhost - tear down the streams stack then rebuild it */ 2644743Smarkm 2744743Smarkmvoid fromhost(request) 2844743Smarkmstruct request_info *request; 2944743Smarkm{ 3044743Smarkm int i; 3144743Smarkm int num_mod; 3244743Smarkm struct str_list str_list; 3344743Smarkm struct str_mlist mod_buffer[MAX_MODULE_COUNT]; 3444743Smarkm int fd = request->fd; 3544743Smarkm 3644743Smarkm str_list.sl_nmods = MAX_MODULE_COUNT; 3744743Smarkm str_list.sl_modlist = &mod_buffer[0]; 3844743Smarkm 3944743Smarkm /* 4044743Smarkm * On systems with WIN streams support we have to be careful about what 4144743Smarkm * is on the stream we are passed. This code POPs off all modules above 4244743Smarkm * the pseudo driver, pushes timod, gets the host address information, 4344743Smarkm * pops timod and then pushes all modules back on the stream. 4444743Smarkm * 4544743Smarkm * Some state may be lost in this process. /usr/etc/tlid seems to do special 4644743Smarkm * things to the stream depending on the TCP port being serviced. (not a 4744743Smarkm * very nice thing to do!). It is unclear what to do if this code breaks 4844743Smarkm * - the stream may be left in an unknown condition. 4944743Smarkm */ 5044743Smarkm if ((num_mod = ioctl(fd, I_LIST, NULL)) < 0) 5144743Smarkm tcpd_warn("fromhost: LIST failed: %m"); 5244743Smarkm if (ioctl(fd, I_LIST, &str_list) < 0) 5344743Smarkm tcpd_warn("fromhost: LIST failed: %m"); 5444743Smarkm 5544743Smarkm /* 5644743Smarkm * POP stream modules except for the driver. 5744743Smarkm */ 5844743Smarkm for (i = 0; i < num_mod - 1; i++) 5944743Smarkm if (ioctl(fd, I_POP, 0) < 0) 6044743Smarkm tcpd_warn("fromhost: POP %s: %m", mod_buffer[i].l_name); 6144743Smarkm 6244743Smarkm /* 6344743Smarkm * PUSH timod so that host address ioctls can be executed. 6444743Smarkm */ 6544743Smarkm if (ioctl(fd, I_PUSH, "timod") < 0) 6644743Smarkm tcpd_warn("fromhost: PUSH timod: %m"); 6744743Smarkm tli_host(request); 6844743Smarkm 6944743Smarkm /* 7044743Smarkm * POP timod, we're done with it now. 7144743Smarkm */ 7244743Smarkm if (ioctl(fd, I_POP, 0) < 0) 7344743Smarkm tcpd_warn("fromhost: POP timod: %m"); 7444743Smarkm 7544743Smarkm /* 7644743Smarkm * Restore stream modules. 7744743Smarkm */ 7844743Smarkm for (i = num_mod - 2; i >= 0; i--) 7944743Smarkm if (ioctl(fd, I_PUSH, mod_buffer[i].l_name) < 0) 8044743Smarkm tcpd_warn("fromhost: PUSH %s: %m", mod_buffer[i].l_name); 8144743Smarkm} 82