diff --git a/src/connection.c b/src/connection.c index 4327c62..d9970b3 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1522,20 +1522,12 @@ static char *socket_ip(int fd, int remote) addrlen = sizeof(addr); - if (remote) { - err = getpeername(fd, (struct sockaddr *)&addr, &addrlen); - if (err != 0) { - mylog(LOG_ERROR, "in getpeername(%d): %s", fd, - strerror(errno)); - return NULL; - } - } else { - err = getsockname(fd, (struct sockaddr *)&addr, &addrlen); - if (err != 0) { - mylog(LOG_ERROR, "in getsockname(%d): %s", fd, - strerror(errno)); - return NULL; - } + /* getsockname every time to get IP version */ + err = getsockname(fd, (struct sockaddr *)&addr, &addrlen); + if (err != 0) { + mylog(LOG_ERROR, "in getsockname(%d): %s", fd, + strerror(errno)); + return NULL; } ip = malloc(65); @@ -1545,13 +1537,25 @@ static char *socket_ip(int fd, int remote) switch (addr.sa_family) { case AF_INET: addrlen4 = sizeof(addr4); - err = getsockname(fd, (struct sockaddr *)&addr4, - &addrlen4); - if (err != 0) { - mylog(LOG_ERROR, "in getsockname(%d): %s", fd, - strerror(errno)); - free(ip); - return NULL; + + if (remote) { + err = getpeername(fd, (struct sockaddr *)&addr4, + &addrlen4); + if (err != 0) { + mylog(LOG_ERROR, "in getpeername(%d): %s", fd, + strerror(errno)); + free(ip); + return NULL; + } + } else { + err = getsockname(fd, (struct sockaddr *)&addr4, + &addrlen4); + if (err != 0) { + mylog(LOG_ERROR, "in getsockname(%d): %s", fd, + strerror(errno)); + free(ip); + return NULL; + } } ret = inet_ntop(AF_INET, &(addr4.sin_addr.s_addr), ip, 64); if (ret == NULL) { @@ -1562,13 +1566,25 @@ static char *socket_ip(int fd, int remote) break; case AF_INET6: addrlen6 = sizeof(addr6); - err = getsockname(fd, (struct sockaddr *)&addr6, - &addrlen6); - if (err != 0) { - mylog(LOG_ERROR, "in getsockname(%d): %s", fd, - strerror(errno)); - free(ip); - return NULL; + + if (remote) { + err = getpeername(fd, (struct sockaddr *)&addr6, + &addrlen6); + if (err != 0) { + mylog(LOG_ERROR, "in getpeername(%d): %s", fd, + strerror(errno)); + free(ip); + return NULL; + } + } else { + err = getsockname(fd, (struct sockaddr *)&addr6, + &addrlen6); + if (err != 0) { + mylog(LOG_ERROR, "in getsockname(%d): %s", fd, + strerror(errno)); + free(ip); + return NULL; + } } ret = inet_ntop(AF_INET6, &(addr6.sin6_addr), ip, 64); if (ret == NULL) { diff --git a/src/irc.c b/src/irc.c index 85ca337..1803e32 100644 --- a/src/irc.c +++ b/src/irc.c @@ -2012,35 +2012,123 @@ void irc_server_shutdown(struct link_server *s) #ifdef HAVE_OIDENTD -/* ugly */ + +#define BIP_OIDENTD_START "## AUTOGENERATED BY BIP. DO NOT EDIT ##\n" +#define BIP_OIDENTD_END "## END OF AUTOGENERATED STUFF ##\n" +#define BIP_OIDENTD_END_LENGTH strlen(BIP_OIDENTD_END) + void oidentd_dump(list_t *connl) { list_iterator_t it; FILE *f; - char *home; - char tmpbuf[256]; - int err; + char *home, *filename, *content; + char *bipstart = NULL, *bipend = NULL; + struct stat stats; + char tag_written = 0; home = getenv("HOME"); - if (!home) + if (home == NULL) { + mylog(LOG_WARN, "Can't get $HOME, not writing oidentd.conf"); return; - strcpy(tmpbuf, home); - strcat(tmpbuf, "/.oidentd.conf"); - f = fopen(tmpbuf, "w"); - if (!f) + } + + filename = (char *)malloc(strlen(home) + strlen("/.oidentd.conf")); + + if(filename == NULL){ + mylog(LOG_WARN, "oidentd_dump : malloc failed, returning"); return; + } + + sprintf(filename, "%s/.oidentd.conf", home); + + if (stat(filename, &stats) == -1) { + if (errno == ENOENT) { + f = fopen(filename, "w+"); + fchmod(fileno(f), 0644); + } else { + mylog(LOG_WARN, "Can't open/create %s", filename); + free(filename); + return; + } + } else { + f = fopen(filename, "r+"); + + if (!f) { + mylog(LOG_WARN, "Can't open/create %s", filename); + free(filename); + return; + } + + content = (char *)malloc(stats.st_size + 1); + + if (content == NULL){ + mylog(LOG_WARN, "oidentd_dump : malloc failed, " + "returning"); + fclose(f); + free(filename); + return; + } + + if (fread(content, 1, stats.st_size, f) != + (size_t)stats.st_size) { + mylog(LOG_WARN, "Can't read %s fully", filename); + goto clean_oidentd; + } + + /* Set terminating zero for strstr */ + content[stats.st_size] = '\0'; + + bipstart = strstr(content, BIP_OIDENTD_START); + if (bipstart != NULL) { + /* We have some config left, rewrite the file + * completely */ + fseek(f, SEEK_SET, 0); + if (ftruncate(fileno(f), 0) == -1) { + mylog(LOG_WARN, "Can't reset %s size", + filename); + goto clean_oidentd; + } + + bipend = strstr(bipstart, BIP_OIDENTD_END); + + /* data preceeding the tag */ + fwrite(content, 1, bipstart - content, f); + + /* data following the tag, if any */ + if (bipend != NULL) + fwrite(bipend + BIP_OIDENTD_END_LENGTH, 1, + stats.st_size - + (bipend - content) - + BIP_OIDENTD_END_LENGTH, f); + else + mylog(LOG_WARN, "No %s mark found in %s", + BIP_OIDENTD_END, filename); + } else { + /* No previous conf */ + if (stats.st_size != 0 && + content[stats.st_size - 1] != '\n') + fprintf(f, "\n"); + } + } for (list_it_init(connl, &it); list_it_item(&it); list_it_next(&it)) { connection_t *c = list_it_item(&it); struct link_any *la = c->user_data; if (c->connected == CONN_OK && la && TYPE(la) == IRC_TYPE_SERVER) { - struct link_server *ls = (struct link_server*)la; - struct link *l = LINK(ls); - + struct link_server *ls; + struct link *l; char *localip, *remoteip; int localport, remoteport; + if (!tag_written) { + fprintf(f, BIP_OIDENTD_START); + tag_written = 1; + } + + ls = (struct link_server*)la; + l = LINK(ls); + localip = connection_localip(CONN(ls)); localport = connection_localport(CONN(ls)); remoteip = connection_remoteip(CONN(ls)); @@ -2055,13 +2143,13 @@ void oidentd_dump(list_t *connl) free(remoteip); } } - fflush(f); + if (tag_written) + fprintf(f, BIP_OIDENTD_END); + +clean_oidentd: fclose(f); - err = chmod(tmpbuf, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (err) { - mylog(LOG_WARN, "Unable to set modes for '%s': %s", tmpbuf, - strerror(errno)); - } + free(content); + free(filename); } #endif