home *** CD-ROM | disk | FTP | other *** search
/ ftp.ee.lbl.gov / 2014.05.ftp.ee.lbl.gov.tar / ftp.ee.lbl.gov / acld-1.11.tar.gz / acld-1.11.tar / acld-1.11 / server.c < prev    next >
C/C++ Source or Header  |  2012-02-07  |  15KB  |  615 lines

  1. /*
  2.  * Copyright (c) 2004, 2006, 2007, 2008, 2009, 2010, 2011
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that: (1) source code distributions
  7.  * retain the above copyright notice and this paragraph in its entirety, (2)
  8.  * distributions including binary code include the above copyright notice and
  9.  * this paragraph in its entirety in the documentation or other materials
  10.  * provided with the distribution, and (3) all advertising materials mentioning
  11.  * features or use of this software display the following acknowledgement:
  12.  * ``This product includes software developed by the University of California,
  13.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14.  * the University nor the names of its contributors may be used to endorse
  15.  * or promote products derived from this software without specific prior
  16.  * written permission.
  17.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20.  */
  21.  
  22. #ifndef lint
  23. static const char rcsid[] =
  24.     "@(#) $Id: server.c 806 2012-02-08 03:40:06Z leres $ (LBL)";
  25. #endif
  26.  
  27. #include <sys/types.h>
  28. #include <sys/time.h>
  29.  
  30. #include <errno.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <sysexits.h>
  35. #include <syslog.h>
  36. #include <unistd.h>
  37.  
  38. #include "acld.h"
  39. #include "cf.h"
  40. #include "child.h"
  41. #include "server.h"
  42.  
  43. /* Forwards */
  44. void servercompactone(struct state *, struct acllist *);
  45. void servercompactport(struct state *, struct acllist *);
  46. void servercompactpermithostport(struct state *, struct acllist *);
  47. void serverdroprestore(struct state *, struct req *);
  48. void servermoveacl(struct state *, struct acllist *, struct acl *, int);
  49.  
  50. void
  51. serverayt(struct state *sp)
  52. {
  53.     struct req *rp;
  54.  
  55.     rp = new(1, sizeof(*rp), "serverayt: req");
  56.     rp->state = RSTATE_PENDING;
  57.     rp->type = REQ_AYT;
  58.     rp->cmd = "ayt";
  59.  
  60.     /* Arrival timestamp */
  61.     getts(&rp->ats);
  62.  
  63.     /* Append the new request to end of list */
  64.     appendreq(&sp->req, rp);
  65. }
  66.  
  67. void
  68. servercompact(struct state *sp)
  69. {
  70.     int i;
  71.     struct acllist *ap;
  72.     struct cf *cf;
  73.  
  74.     cf = sp->cf;
  75.     for (i = 0, ap = cf->c_acllist; i < cf->c_acllistlen; ++i, ++ap) {
  76.         if (ap->compactseq > 0) {
  77.             servercompactone(sp, ap);
  78.             break;
  79.         }
  80.         if (ap->compactportseq > 0) {
  81.             servercompactport(sp, ap);
  82.             break;
  83.         }
  84.         if (ap->compactpermithostportseq > 0) {
  85.             servercompactpermithostport(sp, ap);
  86.             break;
  87.         }
  88.     }
  89.  
  90.     /* Reschedule if we're not done yet */
  91.     if (ap->compactseq > 0 ||
  92.         ap->compactportseq > 0 ||
  93.         ap->compactpermithostportseq > 0) {
  94.         timerset(&sp->t_compact, 0);
  95.         return;
  96.     }
  97.  
  98.     /* Terminado! */
  99.     timerreset(&sp->t_compact);
  100.  
  101.     /* Schedule a sync */
  102.     if (sp->cf->c_sync_secs > 0 && timercheck(&sp->t_sync) < 0)
  103.         timerset(&sp->t_sync, sp->cf->c_sync_secs);
  104.  
  105.     lg(LOG_INFO, "servercompact: finished compacting ACL %s", ap->name);
  106.  
  107.     /* Tell client the good news */
  108.     if (ap->compactclient != NULL) {
  109.         /*
  110.          * XXX What happens if the client goes away
  111.          * before we get here?
  112.          */
  113.         if (ap->compactreq == NULL)
  114.             abort();
  115.         clientsend(ap->compactclient, ap->compactreq);
  116.         freereq(ap->compactreq);
  117.         ap->compactclient = NULL;
  118.         ap->compactreq = NULL;
  119.     }
  120. }
  121.  
  122. void
  123. servercompactone(struct state *sp, struct acllist *ap)
  124. {
  125.     int n, inc, seq;
  126.     struct acl *al;
  127.  
  128.     n = ap->acllen;
  129.     if (sp->cf->c_incrseq) {
  130.         al = ap->acl;
  131.         inc = 1;
  132.     } else {
  133.         al = ap->acl + n - 1;
  134.         inc = -1;
  135.     }
  136.  
  137.     /* Host block range */
  138.     for (; n > 0; --n, al += inc) {
  139.         if (al->seq < sp->cf->c_lowseq || al->seq > sp->cf->c_highseq)
  140.             continue;
  141.         if (sp->cf->c_incrseq) {
  142.             if (al->seq < ap->compactseq)
  143.                 continue;
  144.         } else {
  145.             if (al->seq > ap->compactseq)
  146.                 continue;
  147.         }
  148.         if (al->type == ATYPE_UNKNOWN) {
  149.             ap->compactseq = 0;
  150.             timerreset(&sp->t_compact);
  151.             lg(LOG_ERR, "servercompactone: Can't handle"
  152.                 " unknown ACL type (seq %d)", al->seq);
  153.             return;
  154.         }
  155.         seq = ap->compactseq;
  156.         ap->compactseq += inc;
  157.         if (al->seq != seq) {
  158.             /* XXX Check to see if it's in use? */
  159.             servermoveacl(sp, ap, al, seq);
  160.             return;
  161.         }
  162.  
  163.         /* XXX paranoid */
  164.         if (sp->cf->c_incrseq) {
  165.             if (ap->compactseq >= sp->cf->c_highseq)
  166.                 abort();
  167.         } else {
  168.             if (ap->compactseq <= sp->cf->c_lowseq)
  169.                 abort();
  170.         }
  171.     }
  172.  
  173.     /* If we got here we're done */
  174.     ap->lastseq = ap->compactseq - inc;
  175.     ap->compactseq = 0;
  176. }
  177.  
  178. void
  179. servercompactport(struct state *sp, struct acllist *ap)
  180. {
  181.     int n, seq;
  182.     struct acl *al;
  183.  
  184.     /* Port block range */
  185.     for (n = ap->acllen, al = ap->acl; n > 0; --n, ++al) {
  186.         if (al->seq < sp->cf->c_lowportseq ||
  187.             al->seq > sp->cf->c_highportseq)
  188.             continue;
  189.         if (al->seq < ap->compactportseq)
  190.             continue;
  191.         if (al->type == ATYPE_UNKNOWN) {
  192.             ap->compactportseq = 0;
  193.             timerreset(&sp->t_compact);
  194.             lg(LOG_ERR, "servercompactport: Can't handle"
  195.                 " unknown ACL type (seq %d)", al->seq);
  196.             return;
  197.         }
  198.         seq = ap->compactportseq;
  199.         ++ap->compactportseq;
  200.         if (al->seq != seq) {
  201.             /* XXX Check to see if it's in use? */
  202.             servermoveacl(sp, ap, al, seq);
  203.             return;
  204.         }
  205.  
  206.         /* XXX paranoid */
  207.         if (ap->compactportseq >= sp->cf->c_highportseq)
  208.             abort();
  209.     }
  210.  
  211.     /* If we got here we're done */
  212.     ap->lastportseq = ap->compactportseq - 1;
  213.     ap->compactportseq = 0;
  214. }
  215.  
  216. void
  217. servercompactpermithostport(struct state *sp, struct acllist *ap)
  218. {
  219.     int n, seq;
  220.     struct acl *al;
  221.  
  222.     /* Port block range */
  223.     for (n = ap->acllen, al = ap->acl; n > 0; --n, ++al) {
  224.         if (al->seq < sp->cf->c_lowpermithostportseq ||
  225.             al->seq > sp->cf->c_highpermithostportseq)
  226.             continue;
  227.         if (al->seq < ap->compactpermithostportseq)
  228.             continue;
  229.         if (al->type == ATYPE_UNKNOWN) {
  230.             ap->compactpermithostportseq = 0;
  231.             timerreset(&sp->t_compact);
  232.             lg(LOG_ERR, "servercompactport: Can't handle"
  233.                 " unknown ACL type (seq %d)", al->seq);
  234.             return;
  235.         }
  236.         seq = ap->compactpermithostportseq;
  237.         ++ap->compactpermithostportseq;
  238.         if (al->seq != seq) {
  239.             /* XXX Check to see if it's in use? */
  240.             servermoveacl(sp, ap, al, seq);
  241.             return;
  242.         }
  243.  
  244.         /* XXX paranoid */
  245.         if (ap->compactpermithostportseq >=
  246.             sp->cf->c_highpermithostportseq)
  247.             abort();
  248.     }
  249.  
  250.     /* If we got here we're done */
  251.     ap->lastpermithostportseq = ap->compactpermithostportseq - 1;
  252.     ap->compactpermithostportseq = 0;
  253. }
  254.  
  255. void
  256. servermoveacl(struct state *sp, struct acllist *ap, struct acl *al, int seq)
  257. {
  258.     struct req *rp;
  259.     int remreq, addreq;
  260.     char compactstr[] = "compact";
  261.  
  262.     switch (al->type) {
  263.  
  264.     case ATYPE_BLOCKHOST:
  265.         remreq = REQ_RESTORE;
  266.         addreq = REQ_DROP;
  267.         break;
  268.  
  269.     case ATYPE_BLOCKNET:
  270.         remreq = REQ_RESTORE;
  271.         addreq = REQ_DROP;
  272.         break;
  273.  
  274.     case ATYPE_BLOCKHOSTHOST:
  275.         remreq = REQ_RESTOREHOSTHOST;
  276.         addreq = REQ_BLOCKHOSTHOST;
  277.         break;
  278.  
  279.     case ATYPE_BLOCKUDPPORT:
  280.         remreq = REQ_RESTOREUDPPORT;
  281.         addreq = REQ_DROPUDPPORT;
  282.         break;
  283.  
  284.     case ATYPE_BLOCKTCPPORT:
  285.         remreq = REQ_RESTORETCPPORT;
  286.         addreq = REQ_DROPTCPPORT;
  287.         break;
  288.  
  289.     case ATYPE_PERMITUDPDSTHOSTPORT:
  290.         remreq = REQ_UNPERMITUDPDSTHOSTPORT;
  291.         addreq = REQ_PERMITUDPDSTHOSTPORT;
  292.         break;
  293.  
  294.     case ATYPE_PERMITTCPDSTHOSTPORT:
  295.         remreq = REQ_UNPERMITTCPDSTHOSTPORT;
  296.         addreq = REQ_PERMITTCPDSTHOSTPORT;
  297.         break;
  298.  
  299.     case ATYPE_BLOCKTCPDSTHOSTPORT:
  300.         remreq = REQ_RESTORETCPDSTHOSTPORT;
  301.         addreq = REQ_DROPTCPDSTHOSTPORT;
  302.         break;
  303.  
  304.     default:
  305.         lg(LOG_ERR, "servermoveacl: bad type %s",
  306.             val2str(str2acl, al->type));
  307.         exit(EX_SOFTWARE);
  308.     }
  309.  
  310.     rp = new(1, sizeof(*rp), "servermoveacl: req 1");
  311.     rp->state = RSTATE_PENDING;
  312.     rp->type = remreq;
  313.     rp->cmd = val2str(cmd2req, rp->type);
  314.     rp->acl = *al;
  315.     rp->aclname = strsave(ap->name);
  316.     aclcopy(&rp->acl, al);
  317.     rp->payload.buf = compactstr;
  318.     rp->payload.len = sizeof(compactstr) - 1;
  319.     rp->payload.size = 0;
  320.     getts(&rp->ats);
  321.     appendreq(&sp->req, rp);
  322.  
  323.     /* Change the sequence number */
  324.     al->seq = seq;
  325.  
  326.     rp = new(1, sizeof(*rp), "servermoveacl: req 2");
  327.     rp->state = RSTATE_PENDING;
  328.     rp->type = addreq;
  329.     rp->cmd = val2str(cmd2req, rp->type);
  330.     rp->acl = *al;
  331.     rp->aclname = strsave(ap->name);
  332.     aclcopy(&rp->acl, al);
  333.     rp->payload.buf = compactstr;
  334.     rp->payload.len = sizeof(compactstr) - 1;
  335.     rp->payload.size = 0;
  336.     getts(&rp->ats);
  337.     appendreq(&sp->req, rp);
  338. }
  339.  
  340. /* XXX unfortunately, this duplicates a lot of childdroprestore() */
  341. void
  342. serverdroprestore(struct state *sp, struct req *rp)
  343. {
  344.     struct acllist *ap;
  345.     struct acl *al;
  346.     char buf[32];
  347.  
  348.     /* XXX server should normally supply the sequence number */
  349.     if (rp->acl.seq == 0) {
  350.         lg(LOG_ERR, "serverdroprestore: seq number shouldn't be zero");
  351.         rp->state = RSTATE_DONE;
  352.         getts(&rp->cts);
  353.         return;
  354.     }
  355.  
  356.     /* Find ACL list */
  357.     switch (rp->acl.type) {
  358.  
  359.     case ATYPE_BLOCKHOST:
  360.     case ATYPE_BLOCKNET:
  361.     case ATYPE_BLOCKHOSTHOST:
  362.     case ATYPE_BLOCKTCPDSTHOSTPORT:
  363.         /* By address */
  364.         ap = aclfindlistbyaddr(sp->cf, &rp->acl.addr1);
  365.         if (ap == NULL) {
  366.             lg(LOG_ERR,
  367.                 "serverdroprestore: can't find acllist for %s",
  368.                 addr2str(&rp->acl.addr1));
  369.             rp->state = RSTATE_DONE;
  370.             getts(&rp->cts);
  371.             return;
  372.         }
  373.         rp->acllist = ap;
  374.         break;
  375.  
  376.     case ATYPE_BLOCKUDPPORT:
  377.     case ATYPE_BLOCKTCPPORT:
  378.         /* By ACL name */
  379.         ap = aclfindlistbyname(sp->cf, rp->aclname);
  380.         if (ap == NULL) {
  381.             lg(LOG_ERR,
  382.                 "serverdroprestore: can't find acllist for %s",
  383.                 rp->acl.port1);
  384.             rp->state = RSTATE_DONE;
  385.             getts(&rp->cts);
  386.             return;
  387.         }
  388.         rp->acllist = ap;
  389.         break;
  390.  
  391.     case ATYPE_PERMITUDPDSTHOSTPORT:
  392.     case ATYPE_PERMITTCPDSTHOSTPORT:
  393.         /* Use default ACL list for permit guys */
  394.         ap = aclfindlistdefault(sp->cf, &rp->acl.addr1);
  395.         if (ap == NULL) {
  396.             lg(LOG_ERR,
  397.                 "serverdroprestore: can't find acllist for %s",
  398.                 addr2str(&rp->acl.addr1));
  399.             rp->state = RSTATE_DONE;
  400.             getts(&rp->cts);
  401.             return;
  402.         }
  403.         rp->acllist = ap;
  404.         break;
  405.  
  406.     default:
  407.         lg(LOG_ERR, "ACL type %d not implemented", rp->acl.type);
  408.         rp->state = RSTATE_DONE;
  409.         getts(&rp->cts);
  410.         return;
  411.     }
  412.  
  413.     /*
  414.      * Since we're just changing the sequence number, and we
  415.      * don't remove the ACL, it should always exist.
  416.      */
  417.     al = aclfindacl(ap, &rp->acl, 0);
  418.     switch (rp->type) {
  419.  
  420.     case REQ_DROP:
  421.     case REQ_RESTORE:
  422.         if (al == NULL) {
  423.             lg(LOG_ERR, "serverdroprestore:"
  424.                 " %s wasn't already blocked in ACL %s!",
  425.                 addr2str(&rp->acl.addr1), ap->name);
  426.             rp->state = RSTATE_DONE;
  427.             getts(&rp->cts);
  428.             return;
  429.         }
  430.         break;
  431.  
  432.     case REQ_BLOCKHOSTHOST:
  433.     case REQ_RESTOREHOSTHOST:
  434.         (void)snprintf(buf, sizeof(buf), "%s",
  435.             addr2str(&rp->acl.addr2));
  436.         if (al == NULL) {
  437.             lg(LOG_ERR, "serverdroprestore:"
  438.                 " %s/%s wasn't already blocked in ACL %s!",
  439.                 addr2str(&rp->acl.addr1), buf, ap->name);
  440.             rp->state = RSTATE_DONE;
  441.             getts(&rp->cts);
  442.             return;
  443.         }
  444.         break;
  445.  
  446.     case REQ_DROPUDPPORT:
  447.     case REQ_DROPTCPPORT:
  448.     case REQ_RESTOREUDPPORT:
  449.     case REQ_RESTORETCPPORT:
  450.         if (al == NULL) {
  451.             lg(LOG_ERR, "serverdroprestore: "
  452.                 " port %s/%s wasn't already blocked in ACL %s!",
  453.                 tcporudpreqstr(rp->type), rp->acl.port1, ap->name);
  454.             rp->state = RSTATE_DONE;
  455.             getts(&rp->cts);
  456.             return;
  457.         }
  458.         break;
  459.  
  460.     case REQ_PERMITUDPDSTHOSTPORT:
  461.     case REQ_PERMITTCPDSTHOSTPORT:
  462.     case REQ_DROPTCPDSTHOSTPORT:
  463.         if (al == NULL) {
  464.             lg(LOG_ERR, "serverdroprestore:"
  465.                 " %s:%s/%s wasn't already permitted in ACL %s!",
  466.                 addr2str(&rp->acl.addr1), tcporudpreqstr(rp->type),
  467.                 rp->acl.port1, ap->name);
  468.             rp->state = RSTATE_DONE;
  469.             getts(&rp->cts);
  470.             return;
  471.         }
  472.         break;
  473.  
  474.     case REQ_UNPERMITUDPDSTHOSTPORT:
  475.     case REQ_UNPERMITTCPDSTHOSTPORT:
  476.     case REQ_RESTORETCPDSTHOSTPORT:
  477.         if (al == NULL) {
  478.             lg(LOG_ERR, "serverdroprestore:"
  479.                 " %s:%s/%s wasn't already permitted in ACL %s!",
  480.                 addr2str(&rp->acl.addr1), tcporudpreqstr(rp->type),
  481.                 rp->acl.port1, ap->name);
  482.             rp->state = RSTATE_DONE;
  483.             getts(&rp->cts);
  484.             return;
  485.         }
  486.         break;
  487.  
  488.     default:
  489.         lg(LOG_ERR, "serverdroprestore: bad type %s (1)",
  490.             val2str(str2acl, al->type));
  491.         exit(EX_SOFTWARE);
  492.     }
  493.  
  494.     /* No need to check the sequence number further, just check the type */
  495.     switch (rp->type) {
  496.  
  497.     case REQ_DROP:
  498.     case REQ_RESTORE:
  499.     case REQ_BLOCKHOSTHOST:
  500.     case REQ_RESTOREHOSTHOST:
  501.     case REQ_DROPTCPPORT:
  502.     case REQ_RESTORETCPPORT:
  503.     case REQ_DROPUDPPORT:
  504.     case REQ_RESTOREUDPPORT:
  505.     case REQ_PERMITUDPDSTHOSTPORT:
  506.     case REQ_UNPERMITUDPDSTHOSTPORT:
  507.     case REQ_PERMITTCPDSTHOSTPORT:
  508.     case REQ_UNPERMITTCPDSTHOSTPORT:
  509.     case REQ_DROPTCPDSTHOSTPORT:
  510.     case REQ_RESTORETCPDSTHOSTPORT:
  511.         break;
  512.  
  513.     default:
  514.         lg(LOG_ERR, "serverdroprestore: bad type %s (2)",
  515.             val2str(str2acl, al->type));
  516.         exit(EX_SOFTWARE);
  517.     }
  518.  
  519.     /* Send the request to the child */
  520.     switch (rp->acl.type) {
  521.  
  522.     case ATYPE_BLOCKHOST:
  523.     case ATYPE_BLOCKNET:
  524.         childsend(sp, "%s %s %s %d",
  525.             rp->cmd, addr2str(&rp->acl.addr1),
  526.             ap->name, rp->acl.seq);
  527.         break;
  528.  
  529.     case ATYPE_BLOCKHOSTHOST:
  530.         (void)snprintf(buf, sizeof(buf), "%s",
  531.             addr2str(&rp->acl.addr2));
  532.         childsend(sp, "%s %s %s %s %d",
  533.             rp->cmd, addr2str(&rp->acl.addr1), buf,
  534.             ap->name, rp->acl.seq);
  535.         break;
  536.  
  537.     case ATYPE_BLOCKUDPPORT:
  538.     case ATYPE_BLOCKTCPPORT:
  539.         childsend(sp, "%s %s %s %d",
  540.             rp->cmd, rp->acl.port1, ap->name, rp->acl.seq);
  541.         break;
  542.  
  543.     case ATYPE_PERMITUDPDSTHOSTPORT:
  544.     case ATYPE_PERMITTCPDSTHOSTPORT:
  545.     case ATYPE_BLOCKTCPDSTHOSTPORT:
  546.         childsend(sp, "%s %s %s %s %d",
  547.             rp->cmd, addr2str(&rp->acl.addr1), rp->acl.port1,
  548.             ap->name, rp->acl.seq);
  549.         break;
  550.  
  551.     default:
  552.         lg(LOG_ERR, "childdroprestore: bad atype %d", rp->acl.type);
  553.         exit(EX_SOFTWARE);
  554.     }
  555.  
  556.     /* Update request state */
  557.     rp->state = RSTATE_CHILD;
  558. }
  559.  
  560. void
  561. serverprocess(struct state *sp, struct req *rp)
  562. {
  563.  
  564.     switch (rp->type) {
  565.  
  566.     case REQ_DROP:
  567.     case REQ_RESTORE:
  568.     case REQ_BLOCKHOSTHOST:
  569.     case REQ_RESTOREHOSTHOST:
  570.     case REQ_DROPUDPPORT:
  571.     case REQ_RESTOREUDPPORT:
  572.     case REQ_DROPTCPPORT:
  573.     case REQ_RESTORETCPPORT:
  574.     case REQ_PERMITUDPDSTHOSTPORT:
  575.     case REQ_UNPERMITUDPDSTHOSTPORT:
  576.     case REQ_PERMITTCPDSTHOSTPORT:
  577.     case REQ_UNPERMITTCPDSTHOSTPORT:
  578.     case REQ_DROPTCPDSTHOSTPORT:
  579.     case REQ_RESTORETCPDSTHOSTPORT:
  580.         serverdroprestore(sp, rp);
  581.         break;
  582.  
  583.     case REQ_AYT:
  584.     case REQ_SYNC:
  585.         childsend(sp, "%s", rp->cmd);
  586.         rp->state = RSTATE_CHILD;
  587.         break;
  588.  
  589.     default:
  590.         lg(LOG_ERR, "serverprocess: unhandled request type %d",
  591.             rp->type);
  592.         exit(EX_SOFTWARE);
  593.     }
  594. }
  595.  
  596. void
  597. serversync(struct state *sp)
  598. {
  599.     struct req *rp;
  600.  
  601.     rp = new(1, sizeof(*rp), "serversync: req");
  602.     rp->state = RSTATE_PENDING;
  603.     rp->type = REQ_SYNC;
  604.     rp->cmd = "sync";
  605.  
  606.     /* Arrival timestamp */
  607.     getts(&rp->ats);
  608.  
  609.     /* Append the new request to end of list */
  610.     appendreq(&sp->req, rp);
  611.  
  612.     /* Cancel possible pending "ayt" */
  613.     timerreset(&sp->t_ayt);
  614. }
  615.