ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hopm/trunk/src/irc.c
(Generate patch)

Comparing hopm/trunk/src/irc.c (file contents):
Revision 5274 by michael, Thu Jan 1 20:00:33 2015 UTC vs.
Revision 5434 by michael, Wed Jan 28 16:44:50 2015 UTC

# Line 1 | Line 1
1   /*
2 < * Copyright (C) 2002-2003  Erik Fears
3 < *
4 < * This program is free software; you can redistribute it and/or
5 < * modify it under the terms of the GNU General Public License
6 < * as published by the Free Software Foundation; either version 2
7 < * of the License, or (at your option) any later version.
8 < *
9 < * This program is distributed in the hope that it will be useful,
10 < * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 < * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 < * GNU General Public License for more details.
13 < *
14 < * You should have received a copy of the GNU General Public License
15 < * along with this program; if not, write to
16 < *
17 < *       The Free Software Foundation, Inc.
18 < *       59 Temple Place - Suite 330
19 < *       Boston, MA  02111-1307, USA.
20 < *
2 > *  Copyright (c) 2002-2003 Erik Fears
3 > *  Copyright (c) 2014-2015 ircd-hybrid development team
4   *
5 + *  This program is free software; you can redistribute it and/or modify
6 + *  it under the terms of the GNU General Public License as published by
7 + *  the Free Software Foundation; either version 2 of the License, or
8 + *  (at your option) any later version.
9 + *
10 + *  This program is distributed in the hope that it will be useful,
11 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 + *  GNU General Public License for more details.
14 + *
15 + *  You should have received a copy of the GNU General Public License
16 + *  along with this program; if not, write to the Free Software
17 + *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
18 + *  USA
19   */
20  
21   #include "setup.h"
# Line 29 | Line 26
26   #include <string.h>
27   #include <sys/types.h>
28   #include <sys/socket.h>
29 + #include <netdb.h>
30   #include <netinet/in.h>
31   #include <arpa/inet.h>
32   #include <poll.h>
# Line 50 | Line 48
48   #include "match.h"
49   #include "compat.h"
50   #include "negcache.h"
51 < #include "malloc.h"
51 > #include "memory.h"
52   #include "main.h"
53  
54  
# Line 65 | Line 63 | static struct ChannelConf *get_channel(c
63   static struct UserInfo *userinfo_create(char *);
64   static void userinfo_free(struct UserInfo *source);
65  
66 < static void m_ping(char **, unsigned int, char *, struct UserInfo *);
67 < static void m_invite(char **, unsigned int, char *, struct UserInfo *);
68 < static void m_privmsg(char **, unsigned int, char *, struct UserInfo *);
69 < static void m_ctcp(char **, unsigned int, char *, struct UserInfo *);
70 < static void m_notice(char **, unsigned int, char *, struct UserInfo *);
71 < static void m_perform(char **, unsigned int, char *, struct UserInfo *);
72 < static void m_userhost(char **, unsigned int, char *, struct UserInfo *);
73 < static void m_cannot_join(char **, unsigned int, char *, struct UserInfo *);
74 < static void m_kill(char **, unsigned int, char *, struct UserInfo *);
66 > static void m_ping(char *[], unsigned int, const char *, const struct UserInfo *);
67 > static void m_invite(char *[], unsigned int, const char *, const struct UserInfo *);
68 > static void m_privmsg(char *[], unsigned int, const char *, const struct UserInfo *);
69 > static void m_ctcp(char *[], unsigned int, const char *, const struct UserInfo *);
70 > static void m_notice(char *[], unsigned int, const char *, const struct UserInfo *);
71 > static void m_perform(char *[], unsigned int, const char *, const struct UserInfo *);
72 > static void m_userhost(char *[], unsigned int, const char *, const struct UserInfo *);
73 > static void m_cannot_join(char *[], unsigned int, const char *, const struct UserInfo *);
74 > static void m_kill(char *[], unsigned int, const char *, const struct UserInfo *);
75  
78 extern struct cnode *nc_head;
76  
77   /*
78   * Certain variables we don't want to allocate memory for over and over
# Line 86 | Line 83 | static char          IRC_RAW[MSGLENMAX];
83   static unsigned int  IRC_RAW_LEN    = 0;         /* Position of IRC_RAW                   */
84   static int           IRC_FD         = 0;         /* File descriptor for IRC client        */
85  
86 < static struct bopm_sockaddr IRC_SVR;             /* Sock Address Struct for IRC server    */
90 < static struct bopm_ircaddr  IRC_LOCAL;           /* Sock Address Struct for Bind          */
86 > static struct sockaddr_storage IRC_SVR;          /* Sock Address Struct for IRC server    */
87  
88   static time_t IRC_LAST = 0;                      /* Last full line of data from irc server*/
89   static time_t IRC_LASTRECONNECT = 0;             /* Time of last reconnection */
# Line 144 | Line 140 | irc_cycle(void)
140    pfd.fd = IRC_FD;
141    pfd.events = POLLIN;
142  
143 <  /* Block .025 seconds to avoid excessive CPU use on poll(). */
144 <  switch (poll(&pfd, 1, 25))
143 >  /* Block .050 seconds to avoid excessive CPU use on poll(). */
144 >  switch (poll(&pfd, 1, 50))
145    {
146      case  0:
147      case -1:
# Line 154 | Line 150 | irc_cycle(void)
150        /* Check if IRC data is available. */
151        if (pfd.revents & POLLIN)
152          irc_read();
153 +      else if (pfd.revents & (POLLERR | POLLHUP))
154 +        irc_reconnect();
155  
156        break;
157    }
# Line 172 | Line 170 | irc_cycle(void)
170   static void
171   irc_init(void)
172   {
173 <  struct bopm_sockaddr bsaddr;
176 <  struct in_addr *irc_host;
173 >  const void *address = NULL;
174  
175    if (IRC_FD)
176      close(IRC_FD);
177  
178    memset(&IRC_SVR, 0, sizeof(IRC_SVR));
182  memset(&IRC_LOCAL, 0, sizeof(IRC_LOCAL));
183  memset(&bsaddr, 0, sizeof(struct bopm_sockaddr));
179  
180    /* Resolve IRC host. */
181 <  if ((irc_host = firedns_resolveip4(IRCItem->server)) == NULL)
181 >  if ((address = firedns_resolveip6(IRCItem->server)))
182    {
183 <    log_printf("IRC -> firedns_resolveip4(\"%s\"): %s", IRCItem->server,
189 <               firedns_strerror(fdns_errno));
190 <    exit(EXIT_FAILURE);
191 <  }
183 >    struct sockaddr_in6 *in = (struct sockaddr_in6 *)&IRC_SVR;
184  
185 <  IRC_SVR.sa4.sin_family = AF_INET;
186 <  IRC_SVR.sa4.sin_port = htons(IRCItem->port);
187 <  IRC_SVR.sa4.sin_addr = *irc_host;
185 >    IRC_SVR.ss_family = AF_INET6;
186 >    in->sin6_port = htons(IRCItem->port);
187 >    memcpy(&in->sin6_addr, address, sizeof(in->sin6_addr));
188 >  }
189 >  else if ((address = firedns_resolveip4(IRCItem->server)))
190 >  {
191 >    struct sockaddr_in *in = (struct sockaddr_in *)&IRC_SVR;
192  
193 <  if (IRC_SVR.sa4.sin_addr.s_addr == INADDR_NONE)
193 >    IRC_SVR.ss_family = AF_INET;
194 >    in->sin_port = htons(IRCItem->port);
195 >    memcpy(&in->sin_addr, address, sizeof(in->sin_addr));
196 >  }
197 >  else
198    {
199 <    log_printf("IRC -> Unknown error resolving remote host (%s)",
200 <               IRCItem->server);
199 >    log_printf("IRC -> firedns_resolveip(\"%s\"): %s", IRCItem->server,
200 >               firedns_strerror(firedns_errno));
201      exit(EXIT_FAILURE);
202    }
203  
204    /* Request file desc for IRC client socket */
205 <  IRC_FD = socket(AF_INET, SOCK_STREAM, 0);
205 >  IRC_FD = socket(IRC_SVR.ss_family, SOCK_STREAM, 0);
206  
207    if (IRC_FD == -1)
208    {
# Line 213 | Line 213 | irc_init(void)
213    /* Bind */
214    if (!EmptyString(IRCItem->vhost))
215    {
216 <    int bindret = 0;
216 >    struct addrinfo hints, *res;
217 >
218 >    memset(&hints, 0, sizeof(hints));
219  
220 <    if (inet_pton(AF_INET, IRCItem->vhost, &(IRC_LOCAL.in4.s_addr)) <= 0)
220 >    hints.ai_family = AF_UNSPEC;
221 >    hints.ai_socktype = SOCK_STREAM;
222 >    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
223 >
224 >    if (getaddrinfo(IRCItem->vhost, NULL, &hints, &res))
225      {
226        log_printf("IRC -> bind(): %s is an invalid address", IRCItem->vhost);
227        exit(EXIT_FAILURE);
228      }
229 <
224 <    bsaddr.sa4.sin_addr.s_addr = IRC_LOCAL.in4.s_addr;
225 <    bsaddr.sa4.sin_family = AF_INET;
226 <    bsaddr.sa4.sin_port = htons(0);
227 <
228 <    bindret = bind(IRC_FD, (struct sockaddr *) &(bsaddr.sa4), sizeof(bsaddr.sa4));
229 <
230 <    if (bindret)
229 >    else if (bind(IRC_FD, res->ai_addr, res->ai_addrlen))
230      {
231        log_printf("IRC -> bind(): error binding to %s: %s", IRCItem->vhost, strerror(errno));
232        exit(EXIT_FAILURE);
233      }
234 +
235 +    freeaddrinfo(res);
236    }
237   }
238  
# Line 250 | Line 251 | irc_send(const char *data, ...)
251   {
252    va_list arglist;
253    char buf[MSGLENMAX];
254 <  int len = 0;
254 >  size_t len = 0;
255  
256    va_start(arglist, data);
257    len = vsnprintf(buf, sizeof(buf), data, arglist);
# Line 294 | Line 295 | irc_send_channels(const char *data, ...)
295    vsnprintf(buf, sizeof(buf), data, arglist);
296    va_end(arglist);
297  
297
298    LIST_FOREACH(node, IRCItem->channels->head)
299    {
300      const struct ChannelConf *chan = node->data;
# Line 317 | Line 317 | irc_connect(void)
317    /* Connect to IRC server as client. */
318    if (connect(IRC_FD, (struct sockaddr *)&IRC_SVR, sizeof(IRC_SVR)) == -1)
319    {
320 <    switch (errno)
321 <    {
322 <      case EISCONN:
323 <        /* Already connected */
324 <        return;
325 <      case ECONNREFUSED:
326 <        log_printf("IRC -> connect(): Connection refused by (%s)",
327 <                   IRCItem->server);
328 <        break;
329 <      case ETIMEDOUT:
330 <        log_printf("IRC -> connect(): Timed out connecting to (%s)",
331 <                   IRCItem->server);
332 <        break;
333 <      case ENETUNREACH:
334 <        log_printf("IRC -> connect(): Network unreachable");
335 <        break;
336 <      case EALREADY:
337 <        /* Previous attempt not complete */
338 <        return;
339 <      default:
340 <        log_printf("IRC -> connect(): Unknown error connecting to (%s)",
341 <                   IRCItem->server);
320 >    log_printf("IRC -> connect(): error connecting to %s: %s",
321 >               IRCItem->server, strerror(errno));
322  
323 <        if (OPT_DEBUG >= 1)
324 <          log_printf("%s", strerror(errno));
345 <    }
323 >    if (errno == EISCONN /* Already connected */ || errno == EALREADY /* Previous attempt not complete */)
324 >      return;
325  
326      /* Try to connect again */
327      irc_reconnect();
# Line 493 | Line 472 | irc_parse(void)
472    while ((pos = strchr(pos, ' ')) && parc <= 17)
473    {
474      /* Avoid excessive spaces and end of IRC_RAW */
475 <    if (*(pos + 1) == ' ' && *(pos + 1) == '\0')
475 >    if (*(pos + 1) == ' ' || *(pos + 1) == '\0')
476      {
477        pos++;
478        continue;
# Line 557 | Line 536 | irc_timer(void)
536      log_printf("IRC -> Timeout awaiting data from server.");
537      irc_reconnect();
538  
539 <    /* Make sure we dont do this again for a while */
539 >    /* Make sure we don't do this again for a while */
540      time(&IRC_LAST);
541    }
542    else if (delta >= IRCItem->readtimeout / 2)
543    {
544      /*
545 <     * Generate some data so high ping times or bugs in certain
567 <     * ircds (*cough* unreal *cough*) don't cause uneeded
545 >     * Generate some data so high ping times don't cause uneeded
546       * reconnections
547       */
548      irc_send("PING :HOPM");
# Line 640 | Line 618 | userinfo_create(char *source)
618  
619    if (nick == NULL || username == NULL || hostname == NULL)
620    {
621 <    MyFree(tmp);
621 >    xfree(tmp);
622      return NULL;
623    }
624  
# Line 649 | Line 627 | userinfo_create(char *source)
627    ret->irc_username = xstrdup(username);
628    ret->irc_hostname = xstrdup(hostname);
629  
630 <  MyFree(tmp);
630 >  xfree(tmp);
631  
632    return ret;
633   };
# Line 669 | Line 647 | userinfo_free(struct UserInfo *source_p)
647    if (source_p == NULL)
648      return;
649  
650 <  MyFree(source_p->irc_nick);
651 <  MyFree(source_p->irc_username);
652 <  MyFree(source_p->irc_hostname);
653 <  MyFree(source_p);
650 >  xfree(source_p->irc_nick);
651 >  xfree(source_p->irc_username);
652 >  xfree(source_p->irc_hostname);
653 >  xfree(source_p);
654   }
655  
656   /* m_perform
# Line 688 | Line 666 | userinfo_free(struct UserInfo *source_p)
666   * the source (parv[0]) is a server.
667   */
668   static void
669 < m_perform(char **parv, unsigned int parc, char *msg, struct UserInfo *notused)
669 > m_perform(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *notused)
670   {
671    node_t *node;
672  
673 <  log_printf("IRC -> Connected to %s:%d", IRCItem->server, IRCItem->port);
673 >  log_printf("IRC -> Connected to %s/%d", IRCItem->server, IRCItem->port);
674  
675    /* Identify to nickserv if needed */
676    if (!EmptyString(IRCItem->nickserv))
# Line 715 | Line 693 | m_perform(char **parv, unsigned int parc
693    /* Join all listed channels. */
694    LIST_FOREACH(node, IRCItem->channels->head)
695    {
696 <    struct ChannelConf *channel = node->data;
696 >    const struct ChannelConf *channel = node->data;
697  
698      if (EmptyString(channel->name))
699        continue;
# Line 737 | Line 715 | m_perform(char **parv, unsigned int parc
715   * the source (parv[0]) is a server.
716   */
717   static void
718 < m_ping(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
718 > m_ping(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
719   {
720    if (parc < 3)
721      return;
# Line 759 | Line 737 | m_ping(char **parv, unsigned int parc, c
737   * the source (parv[0]) is a server.
738   */
739   static void
740 < m_invite(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
740 > m_invite(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
741   {
742 <  struct ChannelConf *channel;
742 >  struct ChannelConf *channel = NULL;
743  
744    if (parc < 4)
745      return;
# Line 785 | Line 763 | m_invite(char **parv, unsigned int parc,
763   * the source (parv[0]) is a server.
764   */
765   static void
766 < m_privmsg(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
766 > m_privmsg(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
767   {
768 <  struct ChannelConf *channel;
768 >  struct ChannelConf *channel = NULL;
769    size_t nick_len;
770  
771    if (source_p == NULL)
# Line 819 | Line 797 | m_privmsg(char **parv, unsigned int parc
797        strncasecmp(parv[3], "!all", 4) == 0)
798    {
799      /* XXX command_parse will alter parv[3]. */
800 <    command_parse(parv[3], msg, channel, source_p);
800 >    command_parse(parv[3], channel, source_p);
801    }
802   }
803  
# Line 834 | Line 812 | m_privmsg(char **parv, unsigned int parc
812   *
813   */
814   static void
815 < m_ctcp(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
815 > m_ctcp(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
816   {
817    if (strncasecmp(parv[3], "\001VERSION\001", 9) == 0)
818      irc_send("NOTICE %s :\001VERSION Hybrid Open Proxy Monitor %s\001",
# Line 854 | Line 832 | m_ctcp(char **parv, unsigned int parc, c
832   *
833   */
834   static void
835 < m_notice(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
835 > m_notice(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
836   {
837    static regex_t *preg = NULL;
838    regmatch_t pmatch[5];
839 <
840 <  static char errmsg[256];
841 <  int errnum, i;
864 <  char *user[4];
865 <
866 <  if (parc < 4)
867 <    return;
839 >  int errnum;
840 >  const char *user[4];
841 >  const node_t *node;
842  
843    /* Not interested in notices from users */
844    if (source_p)
845      return;
846  
847 +  if (parc < 4)
848 +    return;
849 +
850    /* Compile the regular expression if it has not been already */
851    if (preg == NULL)
852    {
# Line 877 | Line 854 | m_notice(char **parv, unsigned int parc,
854  
855      if ((errnum = regcomp(preg, IRCItem->connregex, REG_ICASE | REG_EXTENDED)))
856      {
857 <      regerror(errnum, preg, errmsg, 256);
857 >      char errmsg[256];
858 >
859 >      regerror(errnum, preg, errmsg, sizeof(errmsg));
860        log_printf("IRC REGEX -> Error when compiling regular expression");
861        log_printf("IRC REGEX -> %s", errmsg);
862  
863 <      MyFree(preg);
863 >      xfree(preg);
864        preg = NULL;
865        return;
866      }
# Line 908 | Line 887 | m_notice(char **parv, unsigned int parc,
887     *   HOSTNAME: pmatch[3].rm_so  TO  pmatch[3].rm_eo
888     *   IP      : pmatch[4].rm_so  TO  pmatch[4].rm_eo
889     */
890 <  for (i = 0; i < 4; ++i)
890 >  for (unsigned int i = 0; i < 4; ++i)
891    {
892      user[i] = (parv[3] + pmatch[i + 1].rm_so);
893      *(parv[3] + pmatch[i + 1].rm_eo) = '\0';
# Line 922 | Line 901 | m_notice(char **parv, unsigned int parc,
901        regfree(preg);
902     */
903  
904 +  LIST_FOREACH(node, IRCItem->notices->head)
905 +    irc_send("NOTICE %s :%s", user[0], node->data);
906 +
907    /* Pass this information off to scan.c */
908    scan_connect(user, msg);
909  
# Line 942 | Line 924 | m_notice(char **parv, unsigned int parc,
924   *
925   */
926   static void
927 < m_userhost(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
927 > m_userhost(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
928   {
929    if (parc < 4)
930      return;
# Line 960 | Line 942 | m_userhost(char **parv, unsigned int par
942   *
943   */
944   static void
945 < m_cannot_join(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
945 > m_cannot_join(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
946   {
947 <  struct ChannelConf *channel;
947 >  const struct ChannelConf *channel = NULL;
948  
949    if (parc < 5)
950      return;
# Line 987 | Line 969 | m_cannot_join(char **parv, unsigned int
969   *
970   */
971   static void
972 < m_kill(char **parv, unsigned int parc, char *msg, struct UserInfo *source_p)
972 > m_kill(char *parv[], unsigned int parc, const char *msg, const struct UserInfo *source_p)
973   {
974    /* Restart hopm to rehash */
975    main_restart();

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)