@(#)Solaris STREAMS and FW-1 19 AUG 2000 Rob Thomas robt@cymru.com Solaris STREAMS and FW-1 tricks While researching some odd STREAMS behaviour on one of my Sun boxes, I created some code that queries a given STREAM for the modules therein. Lo and behold, I found the FW-1 module embedded in the layer two virtual device STREAM; for example /dev/le, /dev/hme, and /dev/qfe. This follows along with the Check Point statement: "FW-1 inserts itself between layers two and three of the IP stack." The actual method is to push a STREAMS module on to the device STREAM, NOT on the IP STREAM (/dev/ip) or higher (/dev/tcp, /dev/udp). As a side benefit, the modiinfo command provides the total size (text, data, BSS) of any given module. On a Solaris box, simply run the modinfo command and grep for fw. Here is an example: : spanky; modinfo | egrep "Id|fw" Id Loadaddr Size Info Rev Module Name 87 f60c9000 92af5 14 1 fw (FW-1 mod v4.0 b7777) 87 f60c9000 92af5 67 1 fw (FW-1 drv v4.0 b7777) Now convert the hex number under the size column to decimal. This yields, for my seven entry test rule base, 600821 bytes. Note that while the mod- ule appears in the output twice, it is actually the same module with diff- erent list.sl_modlist[x].l_name entries. Here is the code to query STREAMS modules. Note that the host must be STREAMS aware. AIX is not completely converted to STREAMS, for example, with STREAMS only in the terminal (termios) drivers. You may also download the code from http://www.cymru.com/Tools. --- snip snip --- /* * @(#)mods.c v1.0 Rob Thomas robt@cymru.com http://www.cymru.com * mods.c - A tool to query and POP modules from a STREAM * Loosely based on some anonymous STREAMS code * The optional -c flag will attempt to POP the module closest * to the STREAM head. * usage: mods [-c] * Example: foo# mods /dev/le */ #include #include #include #include #include #include int main(int argc, char **argv) { int nmod, loop, fd, opt, pop=0; struct strioctl str; struct str_list list; while ((opt = getopt(argc, argv, "c")) != -1) { switch(opt) { case 'c': pop++; break; } } if (pop > 0) { fd = open(argv[2], O_RDWR); } else { fd = open(argv[1], O_RDWR); } if (fd < 1) { perror("open"); exit(1); } nmod = ioctl(fd, I_LIST, (caddr_t)NULL); if (nmod < 0) { perror("mod query"); exit(3); } printf("The number of modules on %s is %d\n", argv[1], nmod); list.sl_nmods = nmod; list.sl_modlist = (struct str_mlist *) malloc(nmod * sizeof(struct str_mlist)); if (ioctl(fd, I_LIST, &list) < 0) { perror("list query"); exit(5); } printf("Modules on %s:\n", argv[1]); for (loop=0; loop < nmod; loop++) { printf("mod %d = %s\n", loop, list.sl_modlist[loop].l_name); } if (pop > 0) { printf("Attempting an I_POP at the STREAM head..."); if (ioctl(fd, I_POP, 0) != 0) { perror("pop"); exit(7); } printf("\n"); } exit(0); } --- snip snip --- Rob Thomas, robt@cymru.com http://www.cymru.com