Changeset 4666

Show
Ignore:
Timestamp:
11/17/08 10:29:27 (2 months ago)
Author:
martin
Message:

separated updown listener to its own class
caching interface names to properly remove rules if interface has changed

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/charon/plugins/updown/Makefile.am

    r4451 r4666  
    55 
    66plugin_LTLIBRARIES = libstrongswan-updown.la 
    7 libstrongswan_updown_la_SOURCES = updown_plugin.h updown_plugin.c  
     7libstrongswan_updown_la_SOURCES = \ 
     8  updown_plugin.h updown_plugin.c \ 
     9  updown_listener.h updown_listener.c  
    810libstrongswan_updown_la_LDFLAGS = -module 
    911 
  • trunk/src/charon/plugins/updown/updown_plugin.c

    r4632 r4666  
    1616 */ 
    1717 
    18 #define _GNU_SOURCE 
    19 #include <stdio.h> 
    20  
    2118#include "updown_plugin.h" 
     19#include "updown_listener.h" 
    2220 
    2321#include <daemon.h> 
    24 #include <config/child_cfg.h> 
    2522 
    2623typedef struct private_updown_plugin_t private_updown_plugin_t; 
     
    3936     * Listener interface, listens to CHILD_SA state changes 
    4037     */ 
    41     listener_t listener; 
     38    updown_listener_t *listener; 
    4239}; 
    43  
    44 /** 
    45  * Run the up/down script 
    46  */ 
    47 static void updown(ike_sa_t *ike_sa, child_sa_t *child_sa, bool up) 
    48 { 
    49     traffic_selector_t *my_ts, *other_ts; 
    50     enumerator_t *enumerator; 
    51     child_cfg_t *config; 
    52     host_t *vip, *me, *other; 
    53     char *script; 
    54      
    55     config = child_sa->get_config(child_sa); 
    56     vip = ike_sa->get_virtual_ip(ike_sa, TRUE); 
    57     script = config->get_updown(config); 
    58     me = ike_sa->get_my_host(ike_sa); 
    59     other = ike_sa->get_other_host(ike_sa); 
    60      
    61     if (script == NULL) 
    62     { 
    63         return; 
    64     } 
    65      
    66     enumerator = child_sa->create_policy_enumerator(child_sa); 
    67     while (enumerator->enumerate(enumerator, &my_ts, &other_ts)) 
    68     { 
    69         char command[1024]; 
    70         char *my_client, *other_client, *my_client_mask, *other_client_mask; 
    71         char *pos, *virtual_ip, *iface; 
    72         FILE *shell; 
    73  
    74         /* get subnet/bits from string */ 
    75         if (asprintf(&my_client, "%R", my_ts) < 0) 
    76         { 
    77             my_client = NULL; 
    78         } 
    79         pos = strchr(my_client, '/'); 
    80         *pos = '\0'; 
    81         my_client_mask = pos + 1; 
    82         pos = strchr(my_client_mask, '['); 
    83         if (pos) 
    84         { 
    85             *pos = '\0'; 
    86         } 
    87         if (asprintf(&other_client, "%R", other_ts) < 0) 
    88         { 
    89             other_client = NULL; 
    90         } 
    91         pos = strchr(other_client, '/'); 
    92         *pos = '\0'; 
    93         other_client_mask = pos + 1; 
    94         pos = strchr(other_client_mask, '['); 
    95         if (pos) 
    96         { 
    97             *pos = '\0'; 
    98         } 
    99  
    100         if (vip) 
    101         { 
    102             if (asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip) < 0) 
    103             { 
    104                 virtual_ip = NULL; 
    105             } 
    106         } 
    107         else 
    108         { 
    109             if (asprintf(&virtual_ip, "") < 0) 
    110             { 
    111                 virtual_ip = NULL; 
    112             } 
    113         } 
    114          
    115         iface = charon->kernel_interface->get_interface( 
    116                                                 charon->kernel_interface, me); 
    117          
    118         /* build the command with all env variables. 
    119          * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing 
    120          */ 
    121         snprintf(command, sizeof(command), 
    122                  "2>&1 " 
    123                 "PLUTO_VERSION='1.1' " 
    124                 "PLUTO_VERB='%s%s%s' " 
    125                 "PLUTO_CONNECTION='%s' " 
    126                 "PLUTO_INTERFACE='%s' " 
    127                 "PLUTO_REQID='%u' " 
    128                 "PLUTO_ME='%H' " 
    129                 "PLUTO_MY_ID='%D' " 
    130                 "PLUTO_MY_CLIENT='%s/%s' " 
    131                 "PLUTO_MY_CLIENT_NET='%s' " 
    132                 "PLUTO_MY_CLIENT_MASK='%s' " 
    133                 "PLUTO_MY_PORT='%u' " 
    134                 "PLUTO_MY_PROTOCOL='%u' " 
    135                 "PLUTO_PEER='%H' " 
    136                 "PLUTO_PEER_ID='%D' " 
    137                 "PLUTO_PEER_CLIENT='%s/%s' " 
    138                 "PLUTO_PEER_CLIENT_NET='%s' " 
    139                 "PLUTO_PEER_CLIENT_MASK='%s' " 
    140                 "PLUTO_PEER_PORT='%u' " 
    141                 "PLUTO_PEER_PROTOCOL='%u' " 
    142                 "%s" 
    143                 "%s" 
    144                 "%s", 
    145                  up ? "up" : "down", 
    146                  my_ts->is_host(my_ts, me) ? "-host" : "-client", 
    147                  me->get_family(me) == AF_INET ? "" : "-v6", 
    148                  config->get_name(config), 
    149                  iface ? iface : "unknown", 
    150                  child_sa->get_reqid(child_sa), 
    151                  me, ike_sa->get_my_id(ike_sa), 
    152                  my_client, my_client_mask, 
    153                  my_client, my_client_mask, 
    154                  my_ts->get_from_port(my_ts), 
    155                  my_ts->get_protocol(my_ts), 
    156                  other, ike_sa->get_other_id(ike_sa), 
    157                  other_client, other_client_mask, 
    158                  other_client, other_client_mask, 
    159                  other_ts->get_from_port(other_ts), 
    160                  other_ts->get_protocol(other_ts), 
    161                  virtual_ip, 
    162                  config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "", 
    163                  script); 
    164         free(my_client); 
    165         free(other_client); 
    166         free(virtual_ip); 
    167         free(iface); 
    168          
    169         DBG3(DBG_CHD, "running updown script: %s", command); 
    170         shell = popen(command, "r"); 
    171  
    172         if (shell == NULL) 
    173         { 
    174             DBG1(DBG_CHD, "could not execute updown script '%s'", script); 
    175             return; 
    176         } 
    177          
    178         while (TRUE) 
    179         { 
    180             char resp[128]; 
    181              
    182             if (fgets(resp, sizeof(resp), shell) == NULL) 
    183             { 
    184                 if (ferror(shell)) 
    185                 { 
    186                     DBG1(DBG_CHD, "error reading output from updown script"); 
    187                     return; 
    188                 } 
    189                 else 
    190                 { 
    191                     break; 
    192                 } 
    193             } 
    194             else 
    195             { 
    196                 char *e = resp + strlen(resp); 
    197                 if (e > resp && e[-1] == '\n') 
    198                 {   /* trim trailing '\n' */ 
    199                     e[-1] = '\0'; 
    200                 } 
    201                 DBG1(DBG_CHD, "updown: %s", resp); 
    202             } 
    203         } 
    204         pclose(shell); 
    205     } 
    206     enumerator->destroy(enumerator); 
    207 } 
    208  
    209 /** 
    210  * Listener implementation 
    211  */ 
    212 static bool child_state_change(listener_t *this, ike_sa_t *ike_sa, 
    213                                child_sa_t *child_sa, child_sa_state_t state) 
    214 { 
    215     child_sa_state_t old; 
    216      
    217     if (ike_sa) 
    218     { 
    219         old = child_sa->get_state(child_sa); 
    220          
    221         if ((old == CHILD_INSTALLED && state != CHILD_REKEYING ) || 
    222             (old == CHILD_DELETING && state == CHILD_DESTROYING)) 
    223         { 
    224             updown(ike_sa, child_sa, FALSE); 
    225         } 
    226         else if (state == CHILD_INSTALLED) 
    227         { 
    228             updown(ike_sa, child_sa, TRUE); 
    229         } 
    230     } 
    231     return TRUE; 
    232 } 
    23340 
    23441/** 
     
    23744static void destroy(private_updown_plugin_t *this) 
    23845{ 
    239     charon->bus->remove_listener(charon->bus, &this->listener); 
     46    charon->bus->remove_listener(charon->bus, &this->listener->listener); 
     47    this->listener->destroy(this->listener); 
    24048    free(this); 
    24149} 
     
    25058    this->public.plugin.destroy = (void(*)(plugin_t*))destroy; 
    25159     
    252     memset(&this->listener, 0, sizeof(listener_t)); 
    253     this->listener.child_state_change = child_state_change; 
    254      
    255     charon->bus->add_listener(charon->bus, &this->listener); 
     60    this->listener = updown_listener_create(); 
     61    charon->bus->add_listener(charon->bus, &this->listener->listener); 
    25662     
    25763    return &this->public.plugin;