LCOV - code coverage report
Current view: top level - lib - network.c (source / functions) Hit Total Coverage
Test: smtpd.info Lines: 34 77 44.2 %
Date: 2015-11-25 19:06:20 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /* This file is part of the cmail project (http://cmail.rocks/)
       2             :  * (c) 2015 Fabian "cbdev" Stumpf
       3             :  * License: Simplified BSD (2-Clause)
       4             :  * For further information, consult LICENSE.txt
       5             :  */
       6             : 
       7         293 : ssize_t network_read(LOGGER log, CONNECTION* client, char* buffer, unsigned bytes){
       8             :         int status;
       9             : 
      10             :         #ifndef CMAIL_NO_TLS
      11         293 :         switch(client->tls_mode){
      12             :                 case TLS_NONE:
      13             :                         //non-tls client
      14         182 :                         return recv(client->fd, buffer, bytes, 0);
      15             :                 case TLS_NEGOTIATE:
      16             :                         //tls handshake not completed
      17          12 :                         status = gnutls_handshake(client->tls_session);
      18          12 :                         if(status){
      19           6 :                                 if(gnutls_error_is_fatal(status)){
      20           0 :                                         logprintf(log, LOG_ERROR, "TLS Handshake reported fatal error: %s\n", gnutls_strerror(status));
      21           0 :                                         return -2;
      22             :                                 }
      23           6 :                                 logprintf(log, LOG_WARNING, "TLS Handshake reported nonfatal error: %s\n", gnutls_strerror(status));
      24           6 :                                 return -1;
      25             :                         }
      26             : 
      27           6 :                         logprintf(log, LOG_INFO, "TLS Handshake completed\n");
      28           6 :                         return 0;
      29             :                 case TLS_ONLY:
      30             :                         //read with tls
      31          99 :                         return gnutls_record_recv(client->tls_session, buffer, bytes);
      32             :         }
      33             :         #else
      34             :         return recv(client->fd, buffer, bytes, 0);
      35             :         #endif
      36             : 
      37           0 :         logprintf(log, LOG_ERROR, "Network read with invalid TLSMODE\n");
      38           0 :         return -2;
      39             : }
      40             : 
      41           0 : int network_connect(LOGGER log, char* host, uint16_t port){
      42           0 :         int sockfd = -1, error;
      43             :         char port_str[20];
      44             :         struct addrinfo hints;
      45             :         struct addrinfo* head;
      46             :         struct addrinfo* iter;
      47             : 
      48           0 :         memset(&hints, 0, sizeof hints);
      49           0 :         hints.ai_family = AF_UNSPEC;
      50           0 :         hints.ai_socktype = SOCK_STREAM;
      51             : 
      52           0 :         snprintf(port_str, sizeof(port_str), "%d", port);
      53             : 
      54           0 :         error = getaddrinfo(host, port_str, &hints, &head);
      55           0 :         if(error){
      56           0 :                 logprintf(log, LOG_WARNING, "getaddrinfo: %s\r\n", gai_strerror(error));
      57           0 :                 return -1;
      58             :         }
      59             : 
      60           0 :         for(iter = head; iter; iter = iter->ai_next){
      61           0 :                 sockfd = socket(iter->ai_family, iter->ai_socktype, iter->ai_protocol);
      62           0 :                 if(sockfd < 0){
      63           0 :                         continue;
      64             :                 }
      65             : 
      66           0 :                 error = connect(sockfd, iter->ai_addr, iter->ai_addrlen);
      67           0 :                 if(error != 0){
      68           0 :                         close(sockfd);
      69           0 :                         continue;
      70             :                 }
      71             : 
      72           0 :                 break;
      73             :         }
      74             : 
      75           0 :         freeaddrinfo(head);
      76           0 :         iter = NULL;
      77             : 
      78           0 :         if(sockfd < 0){
      79           0 :                 logprintf(log, LOG_WARNING, "Failed to create client socket: %s\n", strerror(errno));
      80           0 :                 return -1;
      81             :         }
      82             : 
      83           0 :         if(error != 0){
      84           0 :                 logprintf(log, LOG_WARNING, "Failed to connect: %s\n", strerror(errno));
      85           0 :                 return -1;
      86             :         }
      87             : 
      88           0 :         return sockfd;
      89             : }
      90             : 
      91           6 : int network_listener(LOGGER log, char* bindhost, char* port){
      92           6 :         int fd = -1, status, yes = 1;
      93             :         struct addrinfo hints;
      94             :         struct addrinfo* info;
      95             :         struct addrinfo* addr_it;
      96             : 
      97           6 :         memset(&hints, 0, sizeof(hints));
      98             : 
      99           6 :         hints.ai_family = AF_UNSPEC;
     100           6 :         hints.ai_socktype = SOCK_STREAM;
     101           6 :         hints.ai_flags = AI_PASSIVE;
     102             : 
     103           6 :         status = getaddrinfo(bindhost, port, &hints, &info);
     104           6 :         if(status != 0){
     105           0 :                 logprintf(log, LOG_ERROR, "Failed to get socket info for %s port %s: %s\n", bindhost, port, gai_strerror(status));
     106           0 :                 return -1;
     107             :         }
     108             : 
     109           6 :         for(addr_it = info; addr_it != NULL; addr_it = addr_it->ai_next){
     110           6 :                 fd = socket(addr_it->ai_family, addr_it->ai_socktype, addr_it->ai_protocol);
     111           6 :                 if(fd < 0){
     112           0 :                         continue;
     113             :                 }
     114             : 
     115           6 :                 if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(yes)) < 0){
     116           3 :                         logprintf(log, LOG_WARNING, "Failed to set IPV6_V6ONLY on socket for %s port %s: %s\n", bindhost, port, strerror(errno));
     117             :                 }
     118             : 
     119           6 :                 yes = 1;
     120           6 :                 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0){
     121           0 :                         logprintf(log, LOG_WARNING, "Failed to set SO_REUSEADDR on socket\n");
     122             :                 }
     123             : 
     124           6 :                 status = bind(fd, addr_it->ai_addr, addr_it->ai_addrlen);
     125           6 :                 if(status < 0){
     126           0 :                         close(fd);
     127           0 :                         continue;
     128             :                 }
     129             : 
     130           6 :                 break;
     131             :         }
     132             : 
     133           6 :         freeaddrinfo(info);
     134             : 
     135           6 :         if(!addr_it){
     136           0 :                 logprintf(log, LOG_ERROR, "Failed to create listening socket for %s port %s\n", bindhost, port);
     137           0 :                 return -1;
     138             :         }
     139             : 
     140           6 :         status = listen(fd, LISTEN_QUEUE_LENGTH);
     141           6 :         if(status < 0){
     142           0 :                 logprintf(log, LOG_ERROR, "Failed to listen on socket: %s", strerror(errno));
     143           0 :                 close(fd);
     144           0 :                 return -1;
     145             :         }
     146             : 
     147           6 :         return fd;
     148             : }

Generated by: LCOV version 1.11