📄 support.c
字号:
/* * Copyright (c) 2001 Mark Fullmer and The Ohio State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $Id: support.c,v 1.35 2003/02/13 02:38:43 maf Exp $ */#include "ftconfig.h"#include "ftlib.h"#include <sys/types.h>#include <sys/stat.h>#include <sys/socket.h>#include <ctype.h>#include <errno.h>#include <limits.h>#include <netdb.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <syslog.h>#include <time.h>#include <fcntl.h>#if HAVE_STRINGS_H #include <strings.h>#endif#if HAVE_STRING_H #include <string.h>#endif#if !HAVE_STRSEP char *strsep (char **, const char *);#endif#ifndef IN_CLASSD_NET#define IN_CLASSD_NET 0xf0000000#endif/* * lookup table for mask length to mask * * (first 8) * 128.0.0.0 192.0.0.0 224.0.0.0 240.0.0.0 * 248.0.0.0 252.0.0.0 254.0.0.0 255.0.0.0 * */u_int32 mask_lookup[] = { 0xffffffff, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff };/* * function ipv4_len2mask * * returns the 32 bit network mask given a length **/u_int32 ipv4_len2mask(u_int8 len){ return mask_lookup[(len > 32) ? 0 : len];}/* * function: load_lookup * * loads a list of , seperated numbers into an array * ! will invert the list * - can be used as a range operator * * example * 1,5-10 == 1,5,6,7,8,9,10 * !1 == all numbers in the range except for 1 */int load_lookup(char *s, int size, char *list){ char *p; int j, k; unsigned i, i2; p = s; while ((*p == ' ') || (*p == '\t')) ++p; if (*p == '!') { for (k = 0; k < size; ++k) list[k] = 1; k = 0; ++p; } else { for (k = 0; k < size; ++k) list[k] = 0; k = 1; } while (*p) { i = (unsigned)strtol(p, (char**)0L, 0); if (i >= size) return -1; list[i] = k; /* skip to , or - */ while (*p && (*p != ',') && (*p != '-')) ++p; if (*p == '-') { ++p; i2 = (unsigned)strtol(p, (char**)0L, 0); if (i2 >= size) return -1; for (j = i; j <= i2; ++j) list[j] = k; /* skip to , or - */ while (*p && (*p != ',') && (*p != '-')) ++p; } /* skip past , and - */ while (*p && ((*p == ',') || (*p == '-'))) ++p; } /* *p */ return 0;} /* load_lookup *//* * function: scan_peeri * * scan peer identifier * * scan 1.2.3.4/1.2.3.4/nn[/nnl] * locip remip port ttl * into ftpeer struct */struct ftpeeri scan_peeri(char *input){ struct ftpeeri ftpi; char *s, *s2, *locip, *remip, *dstport, *ttl; bzero (&ftpi, sizeof ftpi); ftpi.dst_port = FT_PORT; locip = remip = dstport = ttl = (char*)0L; if (!(s = malloc(strlen(input)+1))) { fterr_warn("malloc"); return ftpi; } /* keep track of original pointer to free */ s2 = s; strcpy(s, input); locip = s; if (*s) { } for (; *s && *s != '/'; ++s); if (*s) { *s = 0; remip = ++s; } for (; *s && *s != '/'; ++s); if (*s) { *s = 0; dstport = ++s; } for (; *s && *s != '/'; ++s); if (*s) { *s = 0; ttl = ++s; } if (locip) ftpi.loc_ip = scan_ip(locip); if (remip) ftpi.rem_ip = scan_ip(remip); if (dstport) ftpi.dst_port = atoi(dstport); if (ttl) ftpi.ttl = atoi(ttl); free (s2); return ftpi; } /* scan_peer */struct ip_prefix scan_ip_prefix(char *input){ struct ip_prefix p; char *s, *s2; int has_slash; has_slash = 0; bzero(&p, sizeof p); for (s = input; *s; ++s) if (*s == '/') { has_slash = 1; break; } if (!has_slash) { p.addr = scan_ip(input); if ((IN_CLASSA(p.addr)) && (p.addr == (p.addr & IN_CLASSA_NET))) p.len = 8; else if ((IN_CLASSB(p.addr)) && (p.addr == (p.addr & IN_CLASSB_NET))) p.len = 16; else if ((IN_CLASSC(p.addr)) && (p.addr == (p.addr & IN_CLASSC_NET))) p.len = 24; else if ((IN_CLASSD(p.addr)) && (p.addr == (p.addr & IN_CLASSD_NET))) p.len = 28; else p.len = 32; } else { if (!(s = malloc(strlen(input)+1))) { fterr_warn("malloc"); return p; } s2 = s; strcpy(s, input); for (; *s2 && *s2 != '/'; ++s2); if (*s2) { *s2 = 0; ++s2; } p.addr = scan_ip(s); p.len = atoi(s2); free (s); } if (p.len > 32) p.len = 32; return p;} /* scan_ip_prefix *//* * function: scan_ip * * IP address in string S is converted to a u_long * (borrowed from tcpdump) * * left shift any partial dotted quads, ie 10 is 0x0a000000 not 0x0a * so scan_ip_prefix() works for standard prefix notation, ie 10/8 */u_long scan_ip(char *s){ struct hostent *he; struct in_addr *ina; u_long addr = 0; u_int n; int dns, shift; char *t; /* if there is anything ascii in here, this may be a hostname */ for (dns = 0, t = s; *t; ++t) { if (islower((int)*t) || isupper((int)*t)) { dns = 1; break; } } if (dns) { if (!(he = gethostbyname(s))) goto numeric; if (he->h_addrtype != AF_INET) goto numeric; if (he->h_length != sizeof (u_int32)) goto numeric; ina = (struct in_addr*)*he->h_addr_list; return (ntohl(ina->s_addr)); } /* dns */ shift = 0;numeric: while (1) { /* n is the nibble */ n = 0; /* nibble's are . bounded */ while (*s && (*s != '.') && (*s != ' ') && (*s != '\t')) n = n * 10 + *s++ - '0'; /* shift in the nibble */ addr <<=8; addr |= n & 0xff; ++shift; /* return on end of string */ if ((!*s) || (*s == ' ') || (*s == '\t')) goto ndone; /* skip the . */ ++s; } /* forever */ndone: for (; shift < 4; ++shift) addr <<=8; return addr;} /* scan_ip *//* * function: print_3float * * format a floating point # to stdout w. 1 trailing space * */void print_3float(float f){ char s[10], *c; sprintf(s, "%-3.3f", f); c = s + 1; printf("%s ", c);} /* print_3float *//* * function: print_3float2 * * format a floating point # to stdout w. 2 trailing spaces * */void print_3float2(float f){ char s[10], *c; sprintf(s, "%-3.3f", f); c = s + 1; printf("%s ", c);} /* print_3float *//* adapted from dd */int64 scan_size(char *val){ u_int64 num, t; char *expr; if ((num = strtoul(val, &expr, 0)) == ULONG_MAX) goto erange; switch(*expr) { case 0: break; case 'b': t = num; num *= 512; if (t > num) goto erange; break; case 'G': t = num; num *= 1024; num *= 1024; num *= 1024; if (t > num) goto erange; break; case 'K': t = num; num *= 1024; if (t > num) goto erange; break; case 'M': t = num; num *= 1024; num *= 1024; if (t > num) goto erange; break; default: goto erange; } return num;erange: return (int64)-1;} /* scan_size */#if HAVE_SIGACTION/* * Function: mysignal() * POSIX style signals. * * signal() has different semantics over different versions of unix. * this emulates signal() with sigaction() to behave like BSD. * * From Stevens Advanced Programming in the UNIX environment * */void *mysignal(int signo, void *func){ struct sigaction act, oact; act.sa_handler = (void*)func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (signo == SIGALRM) {#ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; /* SunOS */#endif } else {#ifdef SA_RESTART act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */#endif } if (sigaction(signo, &act, &oact) < 0) return SIG_ERR; return oact.sa_handler;} /* signal */#else /* SIGACTION */void *mysignal(int signo, void *func){ return signal(signo, func) };#endif /* SIGACTION */int unlink_pidfile(int pid, char *file, u_int16 port){ char *c; int ret; if (!(c = (char*)malloc(strlen(file)+16))) return -1; sprintf(c, "%s.%d", file, (int)port); if ((ret = unlink(c)) < 0) fterr_warn("unlink(%s)", c); free (c); return ret;} /* unlink_pidfile */ int write_pidfile(int pid, char *file, u_int16 port){ int fd, len; char str[16], *c; if (!(c = (char*)malloc(strlen(file)+16))) return -1; sprintf(c, "%s.%d", file, (int)port); len = sprintf(str, "%u\n", (unsigned)pid); if ((fd = open(c, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0 ) { fterr_warn("open(%s)", c); free (c); return -1; } if (write(fd, str, len) != len) { fterr_warn("write(%s)", c); close (fd); free (c); return -1; } return close (fd);} /* write_pidfile *//* * function get_gmtoff * * return offset from GMT in seconds * * based on compute_tz() code by Michael R. Elkins */int get_gmtoff(time_t t) { struct tm *tmp, local, gmt; time_t t2; int yday; tmp = gmtime(&t); bcopy(tmp, &gmt, sizeof gmt); tmp = localtime(&t); bcopy(tmp, &local, sizeof local); /* calculate difference in seconds */ t2 = (local.tm_hour - gmt.tm_hour) * 60; /* to minutes */ t2 += (local.tm_min - gmt.tm_min); /* minutes */ t2 *= 60; /* to seconds */ /* diff day */ yday = (local.tm_yday - gmt.tm_yday); if ((yday == -1) || (yday > 1)) t2 -= 86400; /* sub one day */ else if (yday != 0) t2 += 86400; /* add one day */ return t2;} /* get_gmtoff *//* * function: bigsockbuf * * There is no portable way to determine the max send and receive buffers * that can be set for a socket, so guess then decrement that guess by * 2K until the call succeeds. If n > 1MB then the decrement by .5MB * instead. * * returns size or -1 for error*/int bigsockbuf(int fd, int dir, int size){ int n, tries; /* initial size */ n = size; tries = 0; while (n > 4096) { if (setsockopt(fd, SOL_SOCKET, dir, (char*)&n, sizeof (n)) < 0) { /* anything other than no buffers available is fatal */ if (errno != ENOBUFS) { fterr_warn("setsockopt(size=%d)", n); return -1; } /* try a smaller value */ if (n > 1024*1024) /* most systems not > 256K bytes w/o tweaking */ n -= 1024*1024; else n -= 2048; ++tries; } else { fterr_info("setsockopt(size=%d)", n); return n; } } /* while */ /* no increase in buffer size */ return 0;} /* bigsockbuf *//* * function: mkpath * * make the path to a filename. * * returns 0: ok * -1 fail **/int mkpath(const char *path, mode_t mode){ char *c, *cs, *c2, *p, *p2; int len, ret, done, nodir; len = strlen(path); c = (char*)0L; ret = -1; done = 0; if (!(c = (char*)malloc(len+1))) { fterr_warn("malloc()"); goto mkpath_out; } if (!(c2 = (char*)malloc(len+1))) { fterr_warn("malloc()"); goto mkpath_out; } cs = c; strcpy(c, path); c2[0] = 0; while (c && !done) { /* break out pathname components in p */ if (!(p = strsep(&c, "/"))) break; /* end of string? */ if (!c) break; for (done = 1, p2 = c; p2 && *p2; ++p2) if (*p2 == '/') { done = 0; break; } /* build path */ strcat(c2, p); nodir = 0; if (p[0] == '.' && p[1] == 0) nodir = 1; if (p[0] == '.' && p[1] == '.' && p[2] == 0) nodir = 1; if (p[0] == 0) nodir = 1; if (!nodir) { if (mkdir(c2, mode) < 0) { if (errno != EEXIST) { fterr_warn("mkdir(%s)", c2); goto mkpath_out; } } } /* nodir */ strcat(c2, "/"); } ret = 0;mkpath_out: if (cs) free(cs); if (c2) free(c2); return ret;} /* mkpath *//* * function: udp_cksum * * calculate checksum of IP pseudo header plus UDP header * */int udp_cksum(struct ip *ip, struct udphdr *up, int len){ u_int16 *word; int sum; word = (u_int16*)&ip->ip_src.s_addr; sum = *word++; sum += *word; word = (u_int16*)&ip->ip_dst.s_addr; sum += *word++; sum += *word; sum += htons(len); sum += IPPROTO_UDP<<8; word = (u_short*)up; sum += *word++; sum += *word++; sum += *word++; return sum;} /* udp_cksum */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -