"Fossies" - the Fresh Open Source Software Archive

Member "ospfd/control.c" (6 Jun 2009, 6670 Bytes) of package /linux/privat/old/openospfd-4.6.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "control.c" see the Fossies "Dox" file reference documentation.

    1 /*  $OpenBSD: control.c,v 1.27 2009/06/06 07:31:26 eric Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 #include <sys/types.h>
   20 #include <sys/stat.h>
   21 #include <sys/socket.h>
   22 #include <sys/un.h>
   23 #include <errno.h>
   24 #include <fcntl.h>
   25 #include <stdlib.h>
   26 #include <string.h>
   27 #include <unistd.h>
   28 
   29 #include "ospfd.h"
   30 #include "ospf.h"
   31 #include "ospfe.h"
   32 #include "log.h"
   33 #include "control.h"
   34 
   35 #define CONTROL_BACKLOG 5
   36 
   37 int control_imsg_relay(struct imsg *imsg);
   38 
   39 struct ctl_conn *control_connbyfd(int);
   40 struct ctl_conn *control_connbypid(pid_t);
   41 void         control_close(int);
   42 
   43 int
   44 control_init(char *path)
   45 {
   46     struct sockaddr_un   sun;
   47     int          fd;
   48     mode_t           old_umask;
   49 
   50     if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
   51         log_warn("control_init: socket");
   52         return (-1);
   53     }
   54 
   55     bzero(&sun, sizeof(sun));
   56     sun.sun_family = AF_UNIX;
   57     strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
   58 
   59     if (unlink(path) == -1)
   60         if (errno != ENOENT) {
   61             log_warn("control_init: unlink %s", path);
   62             close(fd);
   63             return (-1);
   64         }
   65 
   66     old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
   67     if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
   68         log_warn("control_init: bind: %s", path);
   69         close(fd);
   70         umask(old_umask);
   71         return (-1);
   72     }
   73     umask(old_umask);
   74 
   75     if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) {
   76         log_warn("control_init: chmod");
   77         close(fd);
   78         (void)unlink(path);
   79         return (-1);
   80     }
   81 
   82     session_socket_blockmode(fd, BM_NONBLOCK);
   83     control_state.fd = fd;
   84 
   85     return (0);
   86 }
   87 
   88 int
   89 control_listen(void)
   90 {
   91 
   92     if (listen(control_state.fd, CONTROL_BACKLOG) == -1) {
   93         log_warn("control_listen: listen");
   94         return (-1);
   95     }
   96 
   97     event_set(&control_state.ev, control_state.fd, EV_READ | EV_PERSIST,
   98         control_accept, NULL);
   99     event_add(&control_state.ev, NULL);
  100 
  101     return (0);
  102 }
  103 
  104 void
  105 control_cleanup(char *path)
  106 {
  107     if (path)
  108         unlink(path);
  109 }
  110 
  111 /* ARGSUSED */
  112 void
  113 control_accept(int listenfd, short event, void *bula)
  114 {
  115     int          connfd;
  116     socklen_t        len;
  117     struct sockaddr_un   sun;
  118     struct ctl_conn     *c;
  119 
  120     len = sizeof(sun);
  121     if ((connfd = accept(listenfd,
  122         (struct sockaddr *)&sun, &len)) == -1) {
  123         if (errno != EWOULDBLOCK && errno != EINTR)
  124             log_warn("control_accept");
  125         return;
  126     }
  127 
  128     session_socket_blockmode(connfd, BM_NONBLOCK);
  129 
  130     if ((c = malloc(sizeof(struct ctl_conn))) == NULL) {
  131         log_warn("control_accept");
  132         close(connfd);
  133         return;
  134     }
  135 
  136     imsg_init(&c->iev.ibuf, connfd);
  137     c->iev.handler = control_dispatch_imsg;
  138     c->iev.events = EV_READ;
  139     event_set(&c->iev.ev, c->iev.ibuf.fd, c->iev.events,
  140         c->iev.handler, &c->iev);
  141     event_add(&c->iev.ev, NULL);
  142 
  143     TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
  144 }
  145 
  146 struct ctl_conn *
  147 control_connbyfd(int fd)
  148 {
  149     struct ctl_conn *c;
  150 
  151     for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->iev.ibuf.fd != fd;
  152         c = TAILQ_NEXT(c, entry))
  153         ;   /* nothing */
  154 
  155     return (c);
  156 }
  157 
  158 struct ctl_conn *
  159 control_connbypid(pid_t pid)
  160 {
  161     struct ctl_conn *c;
  162 
  163     for (c = TAILQ_FIRST(&ctl_conns); c != NULL && c->iev.ibuf.pid != pid;
  164         c = TAILQ_NEXT(c, entry))
  165         ;   /* nothing */
  166 
  167     return (c);
  168 }
  169 
  170 void
  171 control_close(int fd)
  172 {
  173     struct ctl_conn *c;
  174 
  175     if ((c = control_connbyfd(fd)) == NULL) {
  176         log_warn("control_close: fd %d: not found", fd);
  177         return;
  178     }
  179 
  180     msgbuf_clear(&c->iev.ibuf.w);
  181     TAILQ_REMOVE(&ctl_conns, c, entry);
  182 
  183     event_del(&c->iev.ev);
  184     close(c->iev.ibuf.fd);
  185     free(c);
  186 }
  187 
  188 /* ARGSUSED */
  189 void
  190 control_dispatch_imsg(int fd, short event, void *bula)
  191 {
  192     struct ctl_conn *c;
  193     struct imsg  imsg;
  194     ssize_t      n;
  195     unsigned int     ifidx;
  196 
  197     if ((c = control_connbyfd(fd)) == NULL) {
  198         log_warn("control_dispatch_imsg: fd %d: not found", fd);
  199         return;
  200     }
  201 
  202     if (event & EV_READ) {
  203         if ((n = imsg_read(&c->iev.ibuf)) == -1 || n == 0) {
  204             control_close(fd);
  205             return;
  206         }
  207     }
  208     if (event & EV_WRITE) {
  209         if (msgbuf_write(&c->iev.ibuf.w) == -1) {
  210             control_close(fd);
  211             return;
  212         }
  213     }
  214 
  215     for (;;) {
  216         if ((n = imsg_get(&c->iev.ibuf, &imsg)) == -1) {
  217             control_close(fd);
  218             return;
  219         }
  220 
  221         if (n == 0)
  222             break;
  223 
  224         switch (imsg.hdr.type) {
  225         case IMSG_CTL_FIB_COUPLE:
  226         case IMSG_CTL_FIB_DECOUPLE:
  227             ospfe_fib_update(imsg.hdr.type);
  228             /* FALLTHROUGH */
  229         case IMSG_CTL_RELOAD:
  230             c->iev.ibuf.pid = imsg.hdr.pid;
  231             ospfe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0);
  232             break;
  233         case IMSG_CTL_KROUTE:
  234         case IMSG_CTL_KROUTE_ADDR:
  235         case IMSG_CTL_IFINFO:
  236             c->iev.ibuf.pid = imsg.hdr.pid;
  237             ospfe_imsg_compose_parent(imsg.hdr.type,
  238                 imsg.hdr.pid, imsg.data,
  239                 imsg.hdr.len - IMSG_HEADER_SIZE);
  240             break;
  241         case IMSG_CTL_SHOW_INTERFACE:
  242             if (imsg.hdr.len == IMSG_HEADER_SIZE +
  243                 sizeof(ifidx)) {
  244                 memcpy(&ifidx, imsg.data, sizeof(ifidx));
  245                 ospfe_iface_ctl(c, ifidx);
  246                 imsg_compose_event(&c->iev, IMSG_CTL_END, 0,
  247                     0, -1, NULL, 0);
  248             }
  249             break;
  250         case IMSG_CTL_SHOW_DATABASE:
  251         case IMSG_CTL_SHOW_DB_EXT:
  252         case IMSG_CTL_SHOW_DB_NET:
  253         case IMSG_CTL_SHOW_DB_RTR:
  254         case IMSG_CTL_SHOW_DB_SELF:
  255         case IMSG_CTL_SHOW_DB_SUM:
  256         case IMSG_CTL_SHOW_DB_ASBR:
  257         case IMSG_CTL_SHOW_RIB:
  258         case IMSG_CTL_SHOW_SUM:
  259             c->iev.ibuf.pid = imsg.hdr.pid;
  260             ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid,
  261                 imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
  262             break;
  263         case IMSG_CTL_SHOW_NBR:
  264             ospfe_nbr_ctl(c);
  265             break;
  266         default:
  267             log_debug("control_dispatch_imsg: "
  268                 "error handling imsg %d", imsg.hdr.type);
  269             break;
  270         }
  271         imsg_free(&imsg);
  272     }
  273 
  274     imsg_event_add(&c->iev);
  275 }
  276 
  277 int
  278 control_imsg_relay(struct imsg *imsg)
  279 {
  280     struct ctl_conn *c;
  281 
  282     if ((c = control_connbypid(imsg->hdr.pid)) == NULL)
  283         return (0);
  284 
  285     return (imsg_compose_event(&c->iev, imsg->hdr.type, 0, imsg->hdr.pid,
  286         -1, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE));
  287 }
  288 
  289 void
  290 session_socket_blockmode(int fd, enum blockmodes bm)
  291 {
  292     int flags;
  293 
  294     if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
  295         fatal("fcntl F_GETFL");
  296 
  297     if (bm == BM_NONBLOCK)
  298         flags |= O_NONBLOCK;
  299     else
  300         flags &= ~O_NONBLOCK;
  301 
  302     if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
  303         fatal("fcntl F_SETFL");
  304 }