1N/A/*
1N/A * CDDL HEADER START
1N/A *
1N/A * The contents of this file are subject to the terms of the
1N/A * Common Development and Distribution License, Version 1.0 only
1N/A * (the "License"). You may not use this file except in compliance
1N/A * with the License.
1N/A *
1N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1N/A * or http://www.opensolaris.org/os/licensing.
1N/A * See the License for the specific language governing permissions
1N/A * and limitations under the License.
1N/A *
1N/A * When distributing Covered Code, include this CDDL HEADER in each
1N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1N/A * If applicable, add the following below this CDDL HEADER, with the
1N/A * fields enclosed by brackets "[]" replaced with your own identifying
1N/A * information: Portions Copyright [yyyy] [name of copyright owner]
1N/A *
1N/A * CDDL HEADER END
1N/A *
1N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#pragma ident "%Z%%M% %I% %E% SMI"
1N/A
1N/A/*
1N/A * mconnect.c - A program to test out SMTP connections.
1N/A * Usage: mconnect [host]
1N/A * ... SMTP dialog
1N/A * ^C or ^D or QUIT
1N/A */
1N/A
1N/A#include <stdio.h>
1N/A#include <stdlib.h>
1N/A#include <signal.h>
1N/A#include <ctype.h>
1N/A#include <string.h>
1N/A#include <strings.h>
1N/A#include <sgtty.h>
1N/A#include <sys/types.h>
1N/A#include <sys/socket.h>
1N/A#include <sys/ioctl.h>
1N/A#include <unistd.h>
1N/A#include <netinet/in.h>
1N/A#include <netdb.h>
1N/A#include <arpa/nameser.h>
1N/A#include <arpa/inet.h>
1N/A#include <errno.h>
1N/A
1N/Aunion bigsockaddr
1N/A{
1N/A struct sockaddr sa; /* general version */
1N/A struct sockaddr_in sin; /* INET family */
1N/A struct sockaddr_in6 sin6; /* INET/IPv6 */
1N/A};
1N/A
1N/Astatic struct sgttyb TtyBuf;
1N/Astatic int raw = 0;
1N/A
1N/A/* ARGSUSED */
1N/Astatic void
1N/Afinis(sig)
1N/A int sig;
1N/A{
1N/A if (raw)
1N/A (void) ioctl(0, TIOCSETP, &TtyBuf);
1N/A exit(0);
1N/A}
1N/A
1N/Aint
1N/Amain(argc, argv)
1N/A int argc;
1N/A char **argv;
1N/A{
1N/A union bigsockaddr SendmailAddress;
1N/A register int s;
1N/A char *host = NULL;
1N/A int pid;
1N/A int on = 1;
1N/A struct servent *sp;
1N/A char buf[1000];
1N/A register FILE *f;
1N/A register struct hostent *hp;
1N/A in_port_t port = 0;
1N/A int err;
1N/A char buf6[INET6_ADDRSTRLEN];
1N/A int addr_num = 0;
1N/A int addrlen;
1N/A
1N/A (void) ioctl(0, TIOCGETP, &TtyBuf);
1N/A (void) signal(SIGINT, finis);
1N/A
1N/A while (--argc > 0)
1N/A {
1N/A register char *p;
1N/A
1N/A p = *++argv;
1N/A if (*p == '-')
1N/A {
1N/A switch (*++p)
1N/A {
1N/A case 'h': /* host */
1N/A break;
1N/A
1N/A case 'p': /* port */
1N/A port = htons(atoi(*++argv));
1N/A argc--;
1N/A break;
1N/A
1N/A case 'r': /* raw connection */
1N/A raw = 1;
1N/A break;
1N/A }
1N/A } else if (host == NULL)
1N/A host = p;
1N/A }
1N/A if (host == NULL)
1N/A host = "localhost";
1N/A
1N/A bzero(&SendmailAddress, sizeof (SendmailAddress));
1N/A hp = getipnodebyname(host, AF_INET6, AI_DEFAULT|AI_ALL, &err);
1N/A if (hp == NULL)
1N/A {
1N/A (void) fprintf(stderr, "mconnect: unknown host %s\r\n", host);
1N/A exit(0);
1N/A }
1N/A
1N/A if (port == 0) {
1N/A sp = getservbyname("smtp", "tcp");
1N/A if (sp != NULL)
1N/A port = sp->s_port;
1N/A }
1N/A
1N/A for (;;) {
1N/A bcopy(hp->h_addr_list[addr_num],
1N/A &SendmailAddress.sin6.sin6_addr, IN6ADDRSZ);
1N/A if (IN6_IS_ADDR_V4MAPPED(&SendmailAddress.sin6.sin6_addr)) {
1N/A SendmailAddress.sa.sa_family = AF_INET;
1N/A SendmailAddress.sin.sin_port = port;
1N/A bcopy(&hp->h_addr_list[addr_num][IN6ADDRSZ - INADDRSZ],
1N/A &SendmailAddress.sin.sin_addr, INADDRSZ);
1N/A addrlen = sizeof (struct sockaddr_in);
1N/A } else {
1N/A SendmailAddress.sa.sa_family = AF_INET6;
1N/A SendmailAddress.sin6.sin6_port = port;
1N/A addrlen = sizeof (struct sockaddr_in6);
1N/A }
1N/A
1N/A s = socket(SendmailAddress.sa.sa_family, SOCK_STREAM, 0);
1N/A if (s < 0)
1N/A {
1N/A perror("socket");
1N/A exit(-1);
1N/A }
1N/A (void) setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *)&on,
1N/A sizeof (on));
1N/A if (SendmailAddress.sa.sa_family == AF_INET)
1N/A (void) printf("connecting to host %s (%s), port %d\r\n",
1N/A host, inet_ntoa(SendmailAddress.sin.sin_addr),
1N/A ntohs(SendmailAddress.sin.sin_port));
1N/A else
1N/A (void) printf("connecting to host %s (%s), port %d\r\n",
1N/A host, inet_ntop(AF_INET6,
1N/A SendmailAddress.sin6.sin6_addr.s6_addr,
1N/A buf6, sizeof (buf6)),
1N/A ntohs(SendmailAddress.sin6.sin6_port));
1N/A if (connect(s, (struct sockaddr *)&SendmailAddress,
1N/A addrlen) >= 0)
1N/A break;
1N/A if (hp->h_addr_list[++addr_num] != NULL) {
1N/A (void) printf("connect failed (%s), next address ...\n",
1N/A strerror(errno));
1N/A bcopy(hp->h_addr_list[addr_num],
1N/A &SendmailAddress.sin6.sin6_addr, IN6ADDRSZ);
1N/A if (IN6_IS_ADDR_V4MAPPED(
1N/A &SendmailAddress.sin6.sin6_addr)) {
1N/A SendmailAddress.sa.sa_family = AF_INET;
1N/A bcopy(&hp->h_addr_list[addr_num]
1N/A [IN6ADDRSZ - INADDRSZ],
1N/A &SendmailAddress.sin.sin_addr,
1N/A INADDRSZ);
1N/A addrlen = sizeof (struct sockaddr_in);
1N/A } else {
1N/A SendmailAddress.sa.sa_family = AF_INET6;
1N/A addrlen = sizeof (struct sockaddr_in6);
1N/A }
1N/A continue;
1N/A }
1N/A perror("connect");
1N/A exit(-1);
1N/A }
1N/A
1N/A if (raw) {
1N/A TtyBuf.sg_flags &= ~CRMOD;
1N/A (void) ioctl(0, TIOCSETP, &TtyBuf);
1N/A TtyBuf.sg_flags |= CRMOD;
1N/A }
1N/A
1N/A /* good connection, fork both sides */
1N/A (void) printf("connection open\n");
1N/A pid = fork();
1N/A if (pid < 0)
1N/A {
1N/A perror("fork");
1N/A exit(-1);
1N/A }
1N/A if (pid == 0)
1N/A {
1N/A /* child -- standard input to sendmail */
1N/A int c;
1N/A
1N/A f = fdopen(s, "w");
1N/A while ((c = fgetc(stdin)) >= 0)
1N/A {
1N/A if (!raw && c == '\n')
1N/A (void) fputc('\r', f);
1N/A (void) fputc(c, f);
1N/A if (c == '\n')
1N/A (void) fflush(f);
1N/A }
1N/A (void) shutdown(s, 1);
1N/A (void) sleep(10);
1N/A }
1N/A else
1N/A {
1N/A /* parent -- sendmail to standard output */
1N/A f = fdopen(s, "r");
1N/A while (fgets(buf, sizeof (buf), f) != NULL)
1N/A {
1N/A (void) fputs(buf, stdout);
1N/A (void) fflush(stdout);
1N/A }
1N/A (void) kill(pid, SIGTERM);
1N/A }
1N/A if (raw)
1N/A (void) ioctl(0, TIOCSETP, &TtyBuf);
1N/A return (0);
1N/A}