⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 这是有名的<<嵌入式系统TCP/IP应用层协议>>,M.Tim Jones 著
💻 C
字号:
/*
 *  Embedded SMTP Server
 *
 *  ./software/ch5/emsmtpd/server.c
 *
 *  mtj@cogitollc.com
 *
 *  Copyright 2001,2002 M. Tim Jones <mtj@cogitollc.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include "server.h"

const char *salutation={"220 Embedded Mail Transport (mtj@mtjones.com)\n"};
const char *conclose={"221 EMT closing connection.\n"};
const char *goahead={"250 OK\n"};
const char *gimmesome={"354 Gimme!\n"};
const char *closeit={"221 Service closing transmission channel.\n"};


parseMailType mail;


/*
 *  closeConnection()
 *
 *  This function performs an SMTP close on the named socket.
 *
 */

void closeConnection(int fd)
{
  write(fd, conclose,  strlen(conclose));
  printf("Aborted the connection...\n");
}


/*
 *  grabAddress()
 *
 *  Grab an address from the line as delimited by '<' and '>'.
 *  Argument 'src' is the input text line of max length 'len', 
 *  and 'dest' is where the email address is copied.
 *
 */

void grabAddress(char *src, char *dest, int len)
{
  int i;
  int j=0;

  for (i = 1 ; i < len ; i++) if (src[i-1] == '<') break;

  if (i == len) { dest[0] = 0; return; }

  for ( ; i < len ; i++) {
    if (src[i] == '>') break;
    dest[j++] = src[i];
  }

  if (i == len) { dest[0] = 0; return; }

  dest[j] = 0;
  return;
}


/*
 *  handleConnection()
 *
 *  This function handles a single SMTP dialog.  The SMTP server protocol
 *  is implemented here as well as buffering of the email header and
 *  body.  This function calls 'parseMail' when an email has been
 *  received to further parse and process the incoming email.
 *
 */

void handleConnection(int fd)
{
  int bufIdx = 0;
  int state = 0, len, i, stop=0;
  char buffer[81];

  memset((void *)&mail, 0, sizeof(mail));

  /* Indicate ready to go... */
  len = write(fd, salutation, strlen(salutation));

  /* Fix the nmap problem. */
  if (len <= 0) {
    return;
  }

  /* Wait for salutation response... */
  len = read(fd, buffer, 255);  buffer[len] = 0;

  if ((strncmp(buffer, "HELO", 4)) && (strncmp(buffer, "EHLO", 4))) {
    closeConnection(fd);
    return;
  }

  write(fd, goahead, strlen(goahead));

  /* Wait for Mail From: */
  len = read(fd, buffer, 255);  buffer[len] = 0;
  if (strncmp(buffer, "MAIL FROM", 9)) { closeConnection(fd); return; }
  grabAddress(buffer, mail.sender, 256);
  if (mail.sender[0] == 0)  { closeConnection(fd); return; }
  write(fd, goahead, strlen(goahead));

  /* Wait for Rcpt To: */
  len = read(fd, buffer, 255);  buffer[len] = 0;
  if (strncmp(buffer, "RCPT TO", 7)) { closeConnection(fd); return; }
  grabAddress(buffer, mail.recipient, 256);
  if (mail.recipient[0] == 0)  { closeConnection(fd); return; }
  write(fd, goahead, strlen(goahead));

  /* Wait for DATA */
  len = read(fd, buffer, 255);  buffer[len] = 0;
  if (strncmp(buffer, "DATA", 4)) { closeConnection(fd); return; }
  write(fd, gimmesome, strlen(gimmesome));

  /* Loop to collect all of the email body */
  bufIdx = state = stop = 0;
  while (!stop) {

    if (bufIdx > MAX_MAIL - 80) { closeConnection(fd); return; }

    len = read(fd, &mail.rawMail[bufIdx], (MAX_MAIL-bufIdx));

    if ((len <= 0) || (bufIdx+len > MAX_MAIL)) {
      closeConnection(fd); return; 
    }

    /* Search for the end in the current buffer */
    for (i = bufIdx ; i < bufIdx+len ; i++) {

      if      ((state == 0) && (mail.rawMail[i] == 0x0d)) state = 1;
      else if ((state == 1) && (mail.rawMail[i] == 0x0a)) state = 2;
      else if ((state == 2) && (mail.rawMail[i] == 0x0d)) state = 1;
      else if ((state == 2) && (mail.rawMail[i] == '.'))  state = 3;
      else if ((state == 3) && (mail.rawMail[i] == 0x0d)) state = 4;
      else if ((state == 4) && (mail.rawMail[i] == 0x0a)) { stop = 1; break; }
      else state = 0;
    }

    bufIdx += len;

  }

  write(fd, goahead, strlen(goahead));

  state = 0;
  while (state++ < 10) {

    // Wait for QUIT
    len = read(fd, buffer, 80);  buffer[len] = 0;

    if (strncmp(buffer, "QUIT", 4)) { 
      closeConnection(fd); return; 
    } else break;

  }

  /* We now have an email in the mail structure, try now to parse it */
  parseMail(&mail, bufIdx);	

  write(fd, closeit, strlen(closeit));

  return;
}


/* 
 *  main()
 *
 *  This main function performs SMTP socket setup and connection
 *  handling.  Calls handleConnection when a peer connects.
 *
 */

int main(int argc, char **argv)
{
  int listenfd, connfd;
  socklen_t clilen;
  struct sockaddr_in cliaddr, servaddr;

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(25);

  bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

  listen(listenfd, 5);

  for ( ; ; ) {

    clilen = sizeof(cliaddr);

    connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);

    if (connfd <= 0) {
      break;
    }

    handleConnection(connfd);

    close(connfd);

  }

  close(listenfd);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -