routevector.c
上传用户:zibowangxu
上传日期:2007-01-04
资源大小:331k
文件大小:15k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /****************************************************************************    
  2.   Copyright (c) 1999 WU-FTPD Development Group.  
  3.   All rights reserved.
  4.    
  5.   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994  
  6.     The Regents of the University of California. 
  7.   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.  
  8.   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.  
  9.   Portions Copyright (c) 1989 Massachusetts Institute of Technology.  
  10.   Portions Copyright (c) 1998 Sendmail, Inc.  
  11.   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.  
  12.   Portions Copyright (c) 1997 by Stan Barber.  
  13.   Portions Copyright (c) 1997 by Kent Landfield.  
  14.   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997  
  15.     Free Software Foundation, Inc.    
  16.    
  17.   Use and distribution of this software and its source code are governed   
  18.   by the terms and conditions of the WU-FTPD Software License ("LICENSE").  
  19.    
  20.   If you did not receive a copy of the license, it may be obtained online  
  21.   at http://www.wu-ftpd.org/license.html.  
  22.    
  23.   $Id: routevector.c,v 1.12 1999/09/22 09:57:12 wuftpd Exp $  
  24.    
  25. ****************************************************************************/
  26. /* GREGORY's comments
  27.  * Use 194.80.17.14 for when the control connection is on any other address
  28.  * passive address 194.80.17.14 0.0.0.0/0
  29.  *
  30.  * My idea for 'passive address' is that the entire ftpaccess be parsed and a
  31.  * table build from them.  The table is sorted (insertion sort is probably
  32.  * good enough) from largest to smallest CIDR mask (/8 then /0).  The first
  33.  * match when top-down searching for the control connection's address is the
  34.  * most-specific and is taken.  If no matches occur at all, use the default
  35.  * address determined from the interface, just as the daemon always has in
  36.  * the past.
  37.  *
  38.  * That's where CIDR comes in.  A /0 means 'match everything'.  If it's
  39.  * there, it'll give the IP address to use everywhere there isn't a more
  40.  * specific remapping given.  If it's not there, we still need something, so
  41.  * we returnthe default from the interface.  In your case, just 0/0 and
  42.  * nobody'll ever see the internal IP numbers.
  43.  */
  44. #include "config.h"
  45. #include <sys/param.h>
  46. #include <sys/types.h>
  47. #include <sys/socket.h>
  48. #include <sys/stat.h>
  49. #include <netinet/in.h>
  50. #include <arpa/inet.h>
  51. #include "../support/ftp.h"
  52. #include <stdio.h>
  53. #include <signal.h>
  54. #include <errno.h>
  55. #include <ctype.h>
  56. #include <pwd.h>
  57. #include <setjmp.h>
  58. #ifdef HAVE_SYS_SYSLOG_H
  59. #include <sys/syslog.h>
  60. #endif
  61. #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H))
  62. #include <syslog.h>
  63. #endif
  64. #ifdef TIME_WITH_SYS_TIME
  65. #include <time.h>
  66. #include <sys/time.h>
  67. #else
  68. #ifdef HAVE_SYS_TIME_H
  69. #include <sys/time.h>
  70. #else
  71. #include <time.h>
  72. #endif
  73. #endif
  74. #include <string.h>
  75. #include <limits.h>
  76. #include "extensions.h"
  77. #include "pathnames.h"
  78. #include "proto.h"
  79. extern struct sockaddr_in ctrl_addr;
  80. extern struct sockaddr_in his_addr; /* added.  _H */
  81. extern struct sockaddr_in vect_addr; /* added.  _H */
  82. static struct sockaddr_in *vector_ptr = (struct sockaddr_in *) NULL;
  83. extern int logging;
  84. extern int log_commands;
  85. extern int debug;
  86. extern char hostname[], remotehost[];
  87. extern int usedefault;
  88. extern int transflag;
  89. extern int data;
  90. extern int errno;
  91. #ifndef MAXHOSTNAMELEN
  92. #define MAXHOSTNAMELEN 64
  93. #endif
  94. /*  The following code is used to create and maintain the 
  95.  *  Address lists using the S_addr struct ( from in.h )
  96.  * struct in_addr { 
  97.  *      union { 
  98.  *              struct { u_char s_b1, s_b2, s_b3, s_b4; } S_un_b; 
  99.  *              struct { u_short s_w1, s_w2; } S_un_w; 
  100.  *              u_long S_addr; 
  101.  *      } S_un; 
  102.  * define s_addr  S_un.S_addr              should be used for all code 
  103.  */
  104. struct v_addr {
  105.     u_long s_external_identity;
  106.     u_long s_vector;
  107.     unsigned short s_sig;
  108. };
  109. typedef struct v_addr v_addr;
  110. struct v_index {
  111.     v_addr *memory;
  112.     v_addr **index;
  113.     unsigned short count;
  114.     unsigned short slots;
  115. };
  116. typedef struct v_index v_index;
  117. struct v_paddr {
  118.     u_long s_address;
  119.     int minport;
  120.     int maxport;
  121.     unsigned short s_sig;
  122. };
  123. typedef struct v_paddr v_paddr;
  124. struct v_ports {
  125.     v_paddr *memory;
  126.     v_paddr **index;
  127.     unsigned short count;
  128.     unsigned short slots;
  129. };
  130. typedef struct v_ports v_ports;
  131. static struct v_index *VECTORS = NULL;
  132. static struct v_ports *PORTS = NULL;
  133. extern int passive_port_max;
  134. extern int passive_port_min;
  135. extern void perror_reply(int, char *);
  136. int routevector(void);
  137. void checkports(void);
  138. static struct v_index *initvectstruct(int num);
  139. static struct v_ports *initportstruct(int num);
  140. static void makeportentry(v_paddr * p, u_long entry, u_short s_sig, char *minport_in, char *maxport_in);
  141. static void makevectentry(v_addr * p, u_long external_identity, u_long vector, u_short s_sig);
  142. static void addportentry(char *address, char *minport, char *maxport);
  143. static void addvectentry(char *external_identity, char *vector);
  144. static void initportvectors(void);
  145. static int addr_cmp(u_long s1, u_short s1_sig, u_long s2, u_short s2_sig);
  146. static int addr_smatch(u_long s1, u_long s2, u_short shift_in);
  147. static v_paddr *find_passive_port_entry(u_long port);
  148. static v_addr *find_passive_vect_entry(u_long e);
  149. int routevector(void)
  150. {
  151.     int vect_addr_set;
  152.     u_long entry;
  153.     v_addr *vaddr;
  154.     extern struct sockaddr_in vect_addr;
  155.     vect_addr_set = 0;
  156.     initportvectors();
  157.     if (VECTORS != NULL) {
  158. entry = ntohl((his_addr.sin_addr.s_addr));
  159. if ((int) entry != -1) {
  160.     vaddr = find_passive_vect_entry(entry);
  161.     if (vaddr != NULL) {
  162. vect_addr.sin_addr.s_addr = htonl(vaddr->s_external_identity);
  163. vect_addr.sin_family = AF_INET;
  164. vect_addr_set = 1;
  165. vector_ptr = &vect_addr;
  166.     }
  167. }
  168.     }
  169. #if 0
  170.     {
  171. extern void debug_listing();
  172. debug_listing();
  173.     }
  174. #endif
  175.     return (vect_addr_set);
  176. }
  177. void checkports(void)
  178. {
  179.     u_long entry;
  180.     v_paddr *addr;
  181.     passive_port_min = -1;
  182.     passive_port_max = -1;
  183.     if (PORTS != NULL) {
  184. entry = his_addr.sin_addr.s_addr;
  185. if ((int) entry != -1) {
  186.     addr = find_passive_port_entry(entry);
  187.     if (addr != NULL) {
  188. passive_port_min = addr->minport;
  189. passive_port_max = addr->maxport;
  190.     }
  191. }
  192.     }
  193. }
  194. static struct v_index *initvectstruct(int num)
  195. {
  196.     int i;
  197.     v_addr *ptr, **index;
  198.     v_index *v;
  199.     if ((v = (v_index *) malloc(sizeof(v_index))) == (v_index *) NULL) {
  200. syslog(LOG_INFO, "ERROR allocating memory for index record");
  201. perror_reply(421, "Local resource failure: malloc");
  202. dologout(1);
  203.     }
  204.     else {
  205. v->count = 0;
  206. v->slots = 0;
  207. v->index = NULL;
  208. if ((v->memory = (v_addr *) malloc(sizeof(v_addr) * num)) == (v_addr *) NULL) {
  209.     syslog(LOG_INFO, "ERROR allocating memory for port addresses");
  210.     perror_reply(421, "Local resource failure: malloc");
  211.     dologout(1);
  212. }
  213. else {
  214.     if ((v->index = (v_addr **) malloc(sizeof(v_addr *) * num)) == (v_addr **) NULL) {
  215. syslog(LOG_INFO, "ERROR allocating memory for vector index");
  216. perror_reply(421, "Local resource failure: malloc");
  217. dologout(1);
  218.     }
  219.     else {
  220. v->slots = num;
  221. for (i = 0, ptr = v->memory, index = v->index; i < num; i++) {
  222.     ptr->s_external_identity = ntohl(inet_addr("0.0.0.0"));
  223.     ptr->s_vector = ntohl(inet_addr("0.0.0.0"));
  224.     ptr->s_sig = (u_short) 0;
  225.     *index++ = ptr++;
  226. }
  227.     }
  228. }
  229.     }
  230.     return (v);
  231. }
  232. static struct v_ports *initportstruct(int num)
  233. {
  234.     int i;
  235.     v_paddr *ptr;
  236.     v_ports *v;
  237.     if ((v = (v_ports *) malloc(sizeof(v_ports))) == (v_ports *) NULL) {
  238. syslog(LOG_INFO, "ERROR allocating memory for index record");
  239. perror_reply(421, "Local resource failure: malloc");
  240. dologout(1);
  241.     }
  242.     else {
  243. v->slots = 0;
  244. v->count = 0;
  245. v->index = NULL;
  246. if ((v->memory = (v_paddr *) malloc(sizeof(v_paddr) * (num + 1))) == (v_paddr *) NULL) {
  247.     syslog(LOG_INFO, "ERROR allocating memory for port addresses");
  248.     perror_reply(421, "Local resource failure: malloc");
  249.     dologout(1);
  250. }
  251. else {
  252.     if ((v->index = (v_paddr **) malloc(sizeof(v_paddr *) * num)) == (v_paddr **) NULL) {
  253. syslog(LOG_INFO, "ERROR allocating memory for port index");
  254. perror_reply(421, "Local resource failure: malloc");
  255. dologout(1);
  256.     }
  257.     else {
  258. v->slots = (u_short) num;
  259. for (i = 0, ptr = v->memory; i < num; i++, ptr++) {
  260.     *(v->index + i) = ptr;
  261.     ptr->s_address = ntohl(inet_addr("0.0.0.0"));
  262.     ptr->minport = -1;
  263.     ptr->maxport = -1;
  264.     ptr->s_sig = (u_short) 0;
  265. }
  266.     }
  267. }
  268.     }
  269.     return (v);
  270. }
  271. static void makeportentry(v_paddr * p, u_long entry, u_short s_sig, char *minport_in, char *maxport_in)
  272. {
  273.     p->s_address = entry;
  274.     p->s_sig = s_sig;
  275.     p->minport = atoi(minport_in);
  276.     p->maxport = atoi(maxport_in);
  277.     if (p->maxport < p->minport) {
  278. p->minport = -1;
  279. p->maxport = -1;
  280.     }
  281. }
  282. static void makevectentry(v_addr * p, u_long external_identity, u_long vector, u_short s_sig)
  283. {
  284.     p->s_external_identity = external_identity;
  285.     p->s_vector = vector;
  286.     p->s_sig = s_sig;
  287. }
  288. static void addportentry(char *address_in, char *minport_in, char *maxport_in)
  289. {
  290.     u_long entry;
  291.     int cmp;
  292.     u_short s_sig;
  293.     char *s1, *s2;
  294.     char addrstr[MAXHOSTNAMELEN + 1];
  295.     register unsigned short i, fnd;
  296.     s_sig = (u_short) 0;
  297.     if (PORTS == NULL) {
  298. syslog(LOG_INFO, "ERROR port index addition, invalid ptr");
  299. perror_reply(421, "Local resource failure: malloc");
  300. dologout(1);
  301.     }
  302.     else {
  303. if (strlen(address_in) > MAXHOSTNAMELEN)
  304.     syslog(LOG_INFO, "ERROR ftpaccess port entry<%s> too large", address_in);
  305. else {
  306.     /* Find the significance of the entry ( if it exists )
  307.        *  eg XXX.XXX.XXX.XXX/sig
  308.      */
  309.     for (i = 0; i < MAXHOSTNAMELEN; i++)
  310. addrstr[i] = '';
  311.     for (s1 = address_in, s2 = &(addrstr[0]); *s1 && *s1 != '/'; s1++, s2++)
  312. *s2 = *s1;
  313.     *s2 = '';
  314.     if (*s1 == '/') {
  315. s1++;
  316. if (*s1)
  317.     s_sig = (u_short) atoi(s1);
  318.     }
  319.     if ((int) (entry = ntohl(inet_addr(addrstr))) == -1)
  320. syslog(LOG_INFO, "ERROR ftpaccess port entry<%s> invalid", address_in);
  321.     else {
  322. for (i = 0, fnd = 0; i < PORTS->count && fnd == 0 && entry != (u_long) 0; i++) {
  323.     v_paddr *vp = *(PORTS->index + i);
  324.     cmp = addr_cmp(vp->s_address, vp->s_sig, entry, s_sig);
  325.     if (cmp == 0) {
  326. fnd = 1;
  327. makeportentry(vp, entry, s_sig, minport_in, maxport_in);
  328.     }
  329.     else if (cmp > 0) {
  330. v_paddr *p1;
  331. for (p1 = *(PORTS->index + PORTS->count); p1 >= vp; p1--)
  332.     *p1 = *(p1 - 1);
  333. fnd = 2;
  334. makeportentry(vp, entry, s_sig, minport_in, maxport_in);
  335. PORTS->count += 1;
  336.     }
  337. }
  338. if (fnd == 0) {
  339.     makeportentry(*(PORTS->index + PORTS->count), entry, s_sig, minport_in, maxport_in);
  340.     PORTS->count += 1;
  341. }
  342. if (i == PORTS->slots) {
  343.     syslog(LOG_INFO, "ERROR bad slot count  for port index record");
  344.     perror_reply(421, "Local resource failure: malloc");
  345.     dologout(1);
  346. }
  347.     }
  348. }
  349.     }
  350. }
  351. static void addvectentry(char *external_identity_in, char *vector_in)
  352. {
  353.     u_long external_identity, vector;
  354.     int cmp;
  355.     u_short s_sig;
  356.     char *s1, *s2;
  357.     char addrstr[MAXHOSTNAMELEN + 1];
  358.     register unsigned short i, fnd;
  359.     s_sig = (u_short) 0;
  360.     if (VECTORS == NULL) {
  361. syslog(LOG_INFO, "ERROR vector index addition, invalid ptr");
  362. perror_reply(421, "Local resource failure: malloc");
  363. dologout(1);
  364.     }
  365.     else {
  366. if (strlen(external_identity_in) > MAXHOSTNAMELEN)
  367.     syslog(LOG_INFO, "ERROR ftpaccess passive entry <%s> to large", external_identity_in);
  368. else {
  369.     if (strlen(vector_in) > MAXHOSTNAMELEN)
  370. syslog(LOG_INFO, "ERROR ftpaccess vector entry<%s> to large", vector_in);
  371.     else {
  372. /* Find the significance of the entry ( if it exists )
  373.    *  eg XXX.XXX.XXX.XXX/sig
  374.  */
  375. for (i = 0; i < MAXHOSTNAMELEN; i++)
  376.     addrstr[i] = '';
  377. for (s1 = vector_in, s2 = &(addrstr[0]); *s1 && (*s1 != '/'); s1++, s2++)
  378.     *s2 = *s1;
  379. *s2 = '';
  380. if (*s1 == '/') {
  381.     s1++;
  382.     if (*s1)
  383. s_sig = (u_short) atoi(s1);
  384. }
  385. if ((int) (vector = ntohl(inet_addr(addrstr))) == -1)
  386.     syslog(LOG_INFO, "ERROR ftpaccess vector entry<%s> invalid", vector_in);
  387. else {
  388.     if ((int) (external_identity = ntohl(inet_addr(external_identity_in))) == -1)
  389. syslog(LOG_INFO, "ERROR ftpaccess vector entry<%s> invalid", external_identity_in);
  390.     else {
  391. for (i = 0, fnd = 0; i < VECTORS->count && fnd == 0 && vector != (u_long) 0; i++) {
  392.     v_addr *vp = *(VECTORS->index + i);
  393.     cmp = addr_cmp(vp->s_vector, vp->s_sig, vector, s_sig);
  394.     if (cmp == 0) {
  395. fnd = 1;
  396. makevectentry(vp, external_identity, vector, s_sig);
  397.     }
  398.     else if (cmp > 0) {
  399. v_addr *p1;
  400. for (p1 = *(VECTORS->index + VECTORS->count); p1 >= vp; p1--)
  401.     *p1 = *(p1 - 1);
  402. fnd = 2;
  403. makevectentry(vp, external_identity, vector, s_sig);
  404. VECTORS->count += 1;
  405.     }
  406. }
  407. if (fnd == 0) {
  408.     makevectentry(*(VECTORS->index + VECTORS->count), external_identity, vector, s_sig);
  409.     VECTORS->count += 1;
  410. }
  411. if (i >= VECTORS->slots) {
  412.     syslog(LOG_INFO, "ERROR bad slot count  for passive vectors index record");
  413.     perror_reply(421, "Local resource failure: malloc");
  414.     dologout(1);
  415. }
  416.     }
  417. }
  418.     }
  419. }
  420.     }
  421. }
  422. static void initportvectors(void)
  423. {
  424.     struct aclmember *entry = NULL;
  425.     int pcnt;
  426.     int acnt;
  427.     pcnt = 0;
  428.     acnt = 0;
  429.     entry = (struct aclmember *) NULL;
  430.     while (getaclentry("passive", &entry)) {
  431. if (!strcasecmp(ARG0, "ports")) {
  432.     if (!ARG0 || !ARG1 || !ARG2)
  433. continue;
  434.     pcnt++;
  435. }
  436. if (!strcasecmp(ARG0, "address")) {
  437.     if (!ARG0 || !ARG1 || !ARG2)
  438. continue;
  439.     acnt++;
  440. }
  441.     }
  442.     PORTS = (pcnt > 0) ? initportstruct(pcnt) : NULL;
  443.     VECTORS = (acnt > 0) ? initvectstruct(acnt) : NULL;
  444.     while (getaclentry("passive", &entry)) {
  445. if (!strcasecmp(ARG0, "ports"))
  446.     addportentry(ARG1, ARG2, ARG3);
  447. else if (!strcasecmp(ARG0, "address"))
  448.     addvectentry(ARG1, ARG2);
  449.     }
  450. }
  451. /* compare two internet masks so that the significance order
  452.  * is from the widest mask down (wide masks match before narrow ones)
  453.  */
  454. static int addr_cmp(u_long s1, u_short s1_sig, u_long s2, u_short s2_sig)
  455. {
  456.     if (s1_sig > s2_sig)
  457. return (-1);
  458.     if (s1_sig < s2_sig)
  459. return (1);
  460.     if (s1 < s2)
  461. return (-1);
  462.     if (s1 > s2)
  463. return (1);
  464.     return (0);
  465. }
  466. /* Compare the first x bits of two internet addresses 
  467.  * 32  means match all ( return is zero on exact match only )
  468.  * 24  means match on first 3 bytes 
  469.  * 16  means match on first 2 bytes 
  470.  *  8  means match on first 1 bytes 
  471.  *  0  means assume match ( match 0 bytes )
  472.  */
  473. #define BITS_PER_BYTE 8
  474. static int addr_smatch(u_long s1, u_long s2, u_short shift_in)
  475. {
  476.     u_long sh1, sh2;
  477.     int shift;
  478.     if (shift_in > 0) {
  479. shift = sizeof(u_long) * BITS_PER_BYTE;
  480. if (shift >= (int) shift_in)
  481.     shift -= (int) shift_in;
  482. if (shift > 0) {
  483.     sh2 = (s2 >> shift) << shift;
  484.     sh1 = (s1 >> shift) << shift;
  485. }
  486. else {
  487.     sh2 = s2;
  488.     sh1 = s1;
  489. }
  490. if (sh1 < sh2)
  491.     return (-1);
  492. if (sh1 > sh2)
  493.     return (1);
  494.     }
  495.     return (0);
  496. }
  497. static v_paddr *find_passive_port_entry(u_long addr)
  498. {
  499.     register int i;
  500.     v_paddr *p;
  501.     if (PORTS != NULL)
  502. for (i = 0; i < PORTS->count; i++) {
  503.     p = *(PORTS->index + i);
  504.     if (addr_smatch(addr, p->s_address, p->s_sig) == 0)
  505. return (p);
  506. }
  507.     return (NULL);
  508. }
  509. static v_addr *find_passive_vect_entry(u_long addr)
  510. {
  511.     register int i;
  512.     v_addr *p;
  513.     if (VECTORS != NULL)
  514. for (i = 0; i < VECTORS->count; i++) {
  515.     p = *(VECTORS->index + i);
  516.     if (addr_smatch(addr, p->s_vector, p->s_sig) == 0)
  517. return (p);
  518. }
  519.     return (NULL);
  520. }