diff options
Diffstat (limited to 'ipsd/sdlpi.c')
-rw-r--r-- | ipsd/sdlpi.c | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/ipsd/sdlpi.c b/ipsd/sdlpi.c new file mode 100644 index 0000000..baede7c --- /dev/null +++ b/ipsd/sdlpi.c @@ -0,0 +1,259 @@ +/* + * (C)opyright 1992-1998 Darren Reed. (from tcplog) + * + * See the IPFILTER.LICENCE file for details on licencing. + * + */ + +#include <stdio.h> +#include <netdb.h> +#include <ctype.h> +#include <fcntl.h> +#include <signal.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/timeb.h> +#include <sys/socket.h> +#include <sys/file.h> +#include <sys/ioctl.h> +#include <sys/stropts.h> + +#include <sys/pfmod.h> +#include <sys/bufmod.h> +#include <sys/dlpi.h> + +#include <net/if.h> +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/if_ether.h> +#include <netinet/ip_var.h> +#include <netinet/udp.h> +#include <netinet/udp_var.h> +#include <netinet/tcp.h> +#include <netinet/tcpip.h> + +#include "ip_compat.h" + +#ifndef lint +static char snitid[] = "%W% %G% (C)1995 Darren Reed"; +#endif + +#define BUFSPACE 32768 + +static int solfd; + +/* + * Be careful to only include those defined in the flags option for the + * interface are included in the header size. + */ +static int timeout; + + +void nullbell() +{ + return 0; +} + + +int ack_recv(ep) +char *ep; +{ + struct tcpiphdr tip; + tcphdr_t *tcp; + ip_t *ip; + + ip = (ip_t *)&tip; + tcp = (tcphdr_t *)(ip + 1); + bcopy(ep, (char *)ip, sizeof(*ip)); + bcopy(ep + (ip->ip_hl << 2), (char *)tcp, sizeof(*tcp)); + + if (ip->ip_off & 0x1fff != 0) + return 0; + if (0 == detect(ip, tcp)) + return 1; + return 0; +} + + +int readloop(fd, port, dst) +int fd, port; +struct in_addr dst; +{ + static u_char buf[BUFSPACE]; + register u_char *bp, *cp, *bufend; + register struct sb_hdr *hp; + register int cc; + struct strbuf dbuf; + ether_header_t eh; + time_t now = time(NULL); + int flags = 0, i, done = 0; + + fd = solfd; + dbuf.len = 0; + dbuf.buf = buf; + dbuf.maxlen = sizeof(buf); + /* + * no control data buffer... + */ + while (1) { + (void) signal(SIGALRM, nullbell); + alarm(1); + i = getmsg(fd, NULL, &dbuf, &flags); + alarm(0); + (void) signal(SIGALRM, nullbell); + + cc = dbuf.len; + if ((time(NULL) - now) > timeout) + return done; + if (i == -1) + if (errno == EINTR) + continue; + else + break; + bp = buf; + bufend = buf + cc; + /* + * loop through each snapshot in the chunk + */ + while (bp < bufend) { + /* + * get past bufmod header + */ + hp = (struct sb_hdr *)bp; + cp = (u_char *)((char *)bp + sizeof(*hp)); + bcopy(cp, (char *)&eh, sizeof(eh)); + /* + * next snapshot + */ + bp += hp->sbh_totlen; + cc -= hp->sbh_totlen; + + if (eh.ether_type != ETHERTYPE_IP) + continue; + + cp += sizeof(eh); + done += ack_recv(cp); + } + alarm(1); + } + perror("getmsg"); + exit(-1); +} + +int initdevice(device, tout) +char *device; +int tout; +{ + struct strioctl si; + struct timeval to; + struct ifreq ifr; + struct packetfilt pfil; + u_long if_flags; + u_short *fwp = pfil.Pf_Filter; + char devname[16], *s, buf[256]; + int i, offset, fd, snaplen= 58, chunksize = BUFSPACE; + + (void) sprintf(devname, "/dev/%s", device); + + s = devname + 5; + while (*s && !ISDIGIT(*s)) + s++; + if (!*s) + { + fprintf(stderr, "bad device name %s\n", devname); + exit(-1); + } + i = atoi(s); + *s = '\0'; + /* + * For reading + */ + if ((fd = open(devname, O_RDWR)) < 0) + { + fprintf(stderr, "O_RDWR(0) "); + perror(devname); + exit(-1); + } + if (dlattachreq(fd, i) == -1 || dlokack(fd, buf) == -1) + { + fprintf(stderr, "DLPI error\n"); + exit(-1); + } + dlbindreq(fd, ETHERTYPE_IP, 0, DL_CLDLS, 0, 0); + dlbindack(fd, buf); + /* + * read full headers + */ + if (strioctl(fd, DLIOCRAW, -1, 0, NULL) == -1) + { + fprintf(stderr, "DLIOCRAW error\n"); + exit(-1); + } + /* + * Create some filter rules for our TCP watcher. We only want ethernet + * pacets which are IP protocol and only the TCP packets from IP. + */ + offset = 6; + *fwp++ = ENF_PUSHWORD + offset; + *fwp++ = ENF_PUSHLIT | ENF_CAND; + *fwp++ = htons(ETHERTYPE_IP); + *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4; + *fwp++ = ENF_PUSHLIT | ENF_AND; + *fwp++ = htons(0x00ff); + *fwp++ = ENF_PUSHLIT | ENF_COR; + *fwp++ = htons(IPPROTO_TCP); + *fwp++ = ENF_PUSHWORD + sizeof(struct ether_header)/sizeof(short)+4; + *fwp++ = ENF_PUSHLIT | ENF_AND; + *fwp++ = htons(0x00ff); + *fwp++ = ENF_PUSHLIT | ENF_CAND; + *fwp++ = htons(IPPROTO_UDP); + pfil.Pf_FilterLen = (fwp - &pfil.Pf_Filter[0]); + /* + * put filter in place. + */ + + if (ioctl(fd, I_PUSH, "pfmod") == -1) + { + perror("ioctl: I_PUSH pf"); + exit(1); + } + if (strioctl(fd, PFIOCSETF, -1, sizeof(pfil), (char *)&pfil) == -1) + { + perror("ioctl: PFIOCSETF"); + exit(1); + } + + /* + * arrange to get messages from the NIT STREAM and use NIT_BUF option + */ + if (ioctl(fd, I_PUSH, "bufmod") == -1) + { + perror("ioctl: I_PUSH bufmod"); + exit(1); + } + i = 128; + strioctl(fd, SBIOCSSNAP, -1, sizeof(i), (char *)&i); + /* + * set the timeout + */ + to.tv_sec = 1; + to.tv_usec = 0; + if (strioctl(fd, SBIOCSTIME, -1, sizeof(to), (char *)&to) == -1) + { + perror("strioctl(SBIOCSTIME)"); + exit(-1); + } + /* + * flush read queue + */ + if (ioctl(fd, I_FLUSH, FLUSHR) == -1) + { + perror("I_FLUSHR"); + exit(-1); + } + timeout = tout; + solfd = fd; + return fd; +} |