smtp_listener.c

// port na którym słuchamy, UID z jakim pracujemy po jego otworzeniu oraz długość kolejki
#define PORT 25
#define WORK_AS_UID 8
#define QUERY_SIZE 3

#include <sys/socket.h>
#include <netinet/ip.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <signal.h>
#include <sys/wait.h>

#include "error_reporting.h"
#include "smtp_talk.h"

int sh;

void end_of_main(int sig) {
  close(sh);
  closelog();
  exit(0);
}

int main(int argv, char *args[]) {
  openlog("smtp_listener", LOG_PID, LOG_DAEMON);
  
  // gniazdo ...
#ifndef IPv4ONLY
  sh = socket(PF_INET6, SOCK_STREAM, 0);
#else
  sh = socket(PF_INET, SOCK_STREAM, 0);
#endif
  if (sh<0) {
    LOG_PRINT_CRIT("socket: %m");
    exit(EXIT_FAILURE);
  }
  
  // funkcja wykonywana po zakonczeniu potomka - unikamy zoombie
  signal(SIGCHLD, SIG_IGN);

  // funkcja wykonywana po Ctrl+C i kill ... unikamy blokowania portu
  signal(SIGTERM, &end_of_main);
  signal(SIGINT, &end_of_main);

  // ustawiamy REUSEADDR na sockecie
  int tmp = 1;
  setsockopt(sh, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp));

  // utworzenie struktury opisującej adres
#ifndef IPv4ONLY
  struct sockaddr_in6 serwer;
  serwer.sin6_family=AF_INET6;
  serwer.sin6_port=htons(PORT);
  serwer.sin6_addr=in6addr_any;

  if (bind(sh, (struct sockaddr *) &serwer, sizeof(struct sockaddr_in6)) < 0) {
#else
  struct sockaddr_in serwer;
  serwer.sin_family=AF_INET;
  serwer.sin_port=htons(PORT);
    // host to network short (porzadek bajtow) ... sa tez dla long i odwrotne ...
  serwer.sin_addr.s_addr=INADDR_ANY;
    // INADDR_ANY oznacza że nasłuchujemy na każdym adresie IP danego hosta
    // (zamiast tego można określić konkretny adres)

  // przypisanie adresu ...
  if (bind(sh, (struct sockaddr *) &serwer, sizeof(struct sockaddr_in)) < 0) {
#endif
    LOG_PRINT_CRIT("bind: %m");
    exit(EXIT_FAILURE);
  }

  // zmiana UIDu
#ifdef WORK_AS_UID
   if (setuid(WORK_AS_UID) < 0) {
    LOG_PRINT_CRIT("Can't drop root privileges: %m");
    close(sh);
    exit(EXIT_FAILURE);
  }
#endif

  // nazwa hosta sie nam przyda ...
  char hostname[64];
  gethostname(hostname, 64);
  
  while(1) {
    // otwarcie portu do nasluchiwania
    if (listen(sh, QUERY_SIZE) < 0) {
      LOG_PRINT_CRIT("listen: %m");
      exit(EXIT_FAILURE);
    }
    
    // odebranie połączenia
#ifndef IPv4ONLY
    struct sockaddr_in6 from;
    socklen_t fromlen=sizeof(struct sockaddr_in6);
#else
    struct sockaddr_in from;
    socklen_t fromlen=sizeof(struct sockaddr_in);
#endif
    int sh2 = accept(sh, (struct sockaddr *) &from, &fromlen);
    
    switch (fork()) {
      case -1: // funkcja zwróciła -1 co oznacza błąd
        LOG_PRINT_ERROR("Error in fork");
        break;
      
      case 0: // funkcja zwróciła zero co oznacza że jesteśmy w procesie potomnym
        close(sh);
        return smtp_talk(sh2, hostname, (struct sockaddr *) &from);
        
      default: // funkcja zwróciła coś innego od 0 i -1 oznacza to że jestesmy w pocesie macierzystym
        close(sh2);
    }
  }

  // zamkniecie gniazda
  close(sh);
  closelog();
}

XHTML generated by highlight (http://www.andre-simon.de/) from smtp_listener.c



Copyright (c) 1999-2015, Robert Paciorek (http://www.opcode.eu.org/), BSD/MIT-type license


Redystrybucja wersji źródłowych i wynikowych, po lub bez dokonywania modyfikacji JEST DOZWOLONA, pod warunkiem zachowania niniejszej informacji o prawach autorskich. Autor NIE ponosi JAKIEJKOLWIEK odpowiedzialności za skutki użytkowania tego dokumentu/programu oraz za wykorzystanie zawartych tu informacji.

This text/program is free document/software. Redistribution and use in source and binary forms, with or without modification, ARE PERMITTED provided save this copyright notice. This document/program is distributed WITHOUT any warranty, use at YOUR own risk.

Valid XHTML 1.1 Dokument ten (URL: http://www.opcode.eu.org/usage_and_config/monitoring/smtp2sms/smtp_listener.c) należy do serwisu OpCode. Autorem tej strony jest Robert Paciorek, wszelkie uwagi proszę kierować na adres e-mail serwisu: webmaster@opcode.eu.org.
Data ostatniej modyfikacji artykulu: '2014-01-07 19:27:42 (UTC)' (data ta może być zafałszowana niemerytorycznymi modyfikacjami artykułu).