Changeset 5c8387e2362c33a8359b6892d55e77b0c5a5be8b

Show
Ignore:
Timestamp:
01/12/11 07:06:15 (4 years ago)
Author:
Theo Schlossnagle <jesus@omniti.com>
git-committer:
Theo Schlossnagle <jesus@omniti.com> 1294815975 +0000
git-parent:

[1f13369b30f3e373a33db896fd3bdf16bad9590d]

git-author:
Theo Schlossnagle <jesus@omniti.com> 1294815975 +0000
Message:

IPv6 support, closes #342

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/modules/ping_icmp.c

    r1f13369 r5c8387e  
    4747#include <netinet/ip.h> 
    4848#include <netinet/ip_icmp.h> 
     49#include <netinet/ip6.h> 
     50#include <netinet/icmp6.h> 
    4951#include <math.h> 
    5052#ifndef MAXFLOAT 
     
    9092  void *payload; 
    9193  int payload_len; 
     94  int icp_len; 
    9295}; 
    9396static noit_log_stream_t nlerr = NULL; 
     
    193196  return 0; 
    194197} 
     198 
    195199static int ping_icmp_handler(eventer_t e, int mask, 
    196                              void *closure, struct timeval *now) { 
     200                             void *closure, struct timeval *now, 
     201                             u_int8_t family) { 
    197202  noit_module_t *self = (noit_module_t *)closure; 
    198203  ping_icmp_data_t *ping_data; 
     
    205210  } from; 
    206211  unsigned int from_len; 
    207   struct ip *ip = (struct ip *)packet; 
    208   struct icmp *icp; 
    209212  struct ping_payload *payload; 
     213 
     214  if(family != AF_INET && family != AF_INET6) return EVENTER_READ; 
    210215 
    211216  ping_data = noit_module_get_userdata(self); 
    212217  while(1) { 
    213218    struct ping_session_key k; 
    214     int inlen, iphlen; 
     219    int inlen; 
     220    u_int8_t iphlen = 0; 
    215221    void *vcheck; 
    216222    noit_check_t *check; 
     
    228234      break; 
    229235    } 
    230     iphlen = ip->ip_hl << 2; 
    231     if((inlen-iphlen) != (sizeof(struct icmp)+PING_PAYLOAD_LEN)) { 
    232       noitLT(nldeb, now, 
    233              "ping_icmp bad size: %d+%d\n", iphlen, inlen-iphlen);  
    234       continue; 
    235     } 
    236     icp = (struct icmp *)(packet + iphlen); 
    237     payload = (struct ping_payload *)(icp + 1); 
    238     if(icp->icmp_type != ICMP_ECHOREPLY) { 
    239       noitLT(nldeb, now, "ping_icmp bad type: %d\n", icp->icmp_type); 
    240       continue; 
    241     } 
    242     if(icp->icmp_id != (((vpsized_uint)self) & 0xffff)) { 
    243       noitLT(nldeb, now, 
    244                "ping_icmp not sent from this instance (%d:%d) vs. %lu\n", 
    245                icp->icmp_id, ntohs(icp->icmp_seq), 
    246                (unsigned long)(((vpsized_uint)self) & 0xffff)); 
     236 
     237    if(family == AF_INET) { 
     238      struct ip *ip = (struct ip *)packet; 
     239      struct icmp *icp4; 
     240      iphlen = ((struct ip *)packet)->ip_hl << 2; 
     241      if((inlen-iphlen) != sizeof(struct icmp)+PING_PAYLOAD_LEN) { 
     242        noitLT(nldeb, now, 
     243               "ping_icmp bad size: %d+%d\n", iphlen, inlen-iphlen);  
     244        continue; 
     245      } 
     246      icp4 = (struct icmp *)(packet + iphlen); 
     247      payload = (struct ping_payload *)(icp4 + 1); 
     248      if(icp4->icmp_type != ICMP_ECHOREPLY) { 
     249        noitLT(nldeb, now, "ping_icmp bad type: %d\n", icp4->icmp_type); 
     250        continue; 
     251      } 
     252      if(icp4->icmp_id != (((vpsized_uint)self) & 0xffff)) { 
     253        noitLT(nldeb, now, 
     254                 "ping_icmp not sent from this instance (%d:%d) vs. %lu\n", 
     255                 icp4->icmp_id, ntohs(icp4->icmp_seq), 
     256                 (unsigned long)(((vpsized_uint)self) & 0xffff)); 
     257        continue; 
     258      } 
     259    } 
     260    else if(family == AF_INET6) { 
     261      struct icmp6_hdr *icp6 = (struct icmp6_hdr *)packet; 
     262      if((inlen) != sizeof(struct icmp6_hdr)+PING_PAYLOAD_LEN) { 
     263        noitLT(nldeb, now, 
     264               "ping_icmp bad size: %d+%d\n", iphlen, inlen-iphlen);  
     265        continue; 
     266      } 
     267      payload = (struct ping_payload *)(icp6+1); 
     268      if(icp6->icmp6_type != ICMP6_ECHO_REPLY) { 
     269        noitLT(nldeb, now, "ping_icmp bad type: %d\n", icp6->icmp6_type); 
     270        continue; 
     271      } 
     272      if(icp6->icmp6_id != (((vpsized_uint)self) & 0xffff)) { 
     273        noitLT(nldeb, now, 
     274                 "ping_icmp not sent from this instance (%d:%d) vs. %lu\n", 
     275                 icp6->icmp6_id, ntohs(icp6->icmp6_seq), 
     276                 (unsigned long)(((vpsized_uint)self) & 0xffff)); 
     277        continue; 
     278      } 
     279    } 
     280    else { 
     281      /* This should be unreachable */ 
    247282      continue; 
    248283    } 
     
    300335  return EVENTER_READ; 
    301336} 
     337static int ping_icmp4_handler(eventer_t e, int mask, 
     338                              void *closure, struct timeval *now) { 
     339  return ping_icmp_handler(e, mask, closure, now, AF_INET); 
     340} 
     341static int ping_icmp6_handler(eventer_t e, int mask, 
     342                              void *closure, struct timeval *now) { 
     343  return ping_icmp_handler(e, mask, closure, now, AF_INET6); 
     344} 
    302345 
    303346static int ping_icmp_init(noit_module_t *self) { 
     
    350393    newe->fd = data->ipv4_fd; 
    351394    newe->mask = EVENTER_READ; 
    352     newe->callback = ping_icmp_handler; 
     395    newe->callback = ping_icmp4_handler; 
    353396    newe->closure = self; 
    354397    eventer_add(newe); 
    355398  } 
    356399 
    357   data->ipv6_fd = socket(AF_INET6, SOCK_RAW, proto->p_proto); 
    358   if(data->ipv6_fd < 0) { 
    359     noitL(noit_error, "ping_icmp: socket failed: %s\n", 
    360           strerror(errno)); 
    361   } 
    362   else { 
    363     if(eventer_set_fd_nonblocking(data->ipv6_fd)) { 
    364       close(data->ipv6_fd); 
    365       data->ipv6_fd = -1; 
    366       noitL(noit_error, 
    367             "ping_icmp: could not set socket non-blocking: %s\n", 
    368                strerror(errno)); 
    369     } 
    370   } 
    371   if(data->ipv6_fd >= 0) { 
    372     eventer_t newe; 
    373     newe = eventer_alloc(); 
    374     newe->fd = data->ipv6_fd; 
    375     newe->mask = EVENTER_READ; 
    376     newe->callback = ping_icmp_handler; 
    377     newe->closure = self; 
    378     eventer_add(newe); 
    379   } 
     400  if ((proto = getprotobyname("ipv6-icmp")) != NULL) { 
     401    data->ipv6_fd = socket(AF_INET6, SOCK_RAW, proto->p_proto); 
     402    if(data->ipv6_fd < 0) { 
     403      noitL(noit_error, "ping_icmp: socket failed: %s\n", 
     404            strerror(errno)); 
     405    } 
     406    else { 
     407      if(eventer_set_fd_nonblocking(data->ipv6_fd)) { 
     408        close(data->ipv6_fd); 
     409        data->ipv6_fd = -1; 
     410        noitL(noit_error, 
     411              "ping_icmp: could not set socket non-blocking: %s\n", 
     412                 strerror(errno)); 
     413      } 
     414    } 
     415    if(data->ipv6_fd >= 0) { 
     416      eventer_t newe; 
     417      newe = eventer_alloc(); 
     418      newe->fd = data->ipv6_fd; 
     419      newe->mask = EVENTER_READ; 
     420      newe->callback = ping_icmp6_handler; 
     421      newe->closure = self; 
     422      eventer_add(newe); 
     423    } 
     424  } 
     425  else 
     426    noitL(noit_error, "Couldn't find 'ipv6-icmp' protocol\n"); 
    380427 
    381428  noit_module_set_userdata(self, data); 
     
    387434  struct ping_closure *pcl = (struct ping_closure *)closure; 
    388435  struct ping_session_key k; 
    389   struct icmp *icp; 
    390436  struct ping_payload *payload; 
    391437  struct timeval whence; 
     
    395441 
    396442  data = noit_module_get_userdata(pcl->self); 
    397   icp = (struct icmp *)pcl->payload; 
    398   payload = (struct ping_payload *)(icp + 1); 
     443  payload = (struct ping_payload *)((char *)pcl->payload + pcl->icp_len); 
    399444  k.addr_of_check = payload->addr_of_check; 
    400445  uuid_copy(k.checkid, payload->checkid); 
     
    412457  payload->tv_sec = whence.tv_sec; 
    413458  payload->tv_usec = whence.tv_usec; 
    414   icp->icmp_cksum = in_cksum(pcl->payload, pcl->payload_len); 
    415459  if(pcl->check->target_family == AF_INET) { 
    416460    struct sockaddr_in sin; 
     461    struct icmp *icp4 = (struct icmp *)pcl->payload; 
     462    icp4->icmp_cksum = in_cksum(pcl->payload, pcl->payload_len); 
    417463    memset(&sin, 0, sizeof(sin)); 
    418464    sin.sin_family = AF_INET; 
     
    425471  else if(pcl->check->target_family == AF_INET6) { 
    426472    struct sockaddr_in6 sin; 
     473    struct icmp6_hdr *icp6 = (struct icmp6_hdr *)pcl->payload; 
     474    icp6->icmp6_cksum = in_cksum(pcl->payload, pcl->payload_len); 
    427475    memset(&sin, 0, sizeof(sin)); 
    428476    sin.sin6_family = AF_INET6; 
     
    456504static int ping_icmp_send(noit_module_t *self, noit_check_t *check) { 
    457505  struct timeval when, p_int; 
    458   struct icmp *icp; 
    459506  struct ping_payload *payload; 
    460507  struct ping_closure *pcl; 
    461508  struct check_info *ci = (struct check_info *)check->closure; 
    462   int packet_len, i
     509  int packet_len, icp_len, i
    463510  eventer_t newe; 
    464511  const char *config_val; 
    465512  ping_icmp_data_t *ping_data; 
    466513  struct ping_session_key *k; 
     514  void *icp; 
    467515 
    468516  int interval = PING_INTERVAL; 
     
    504552  p_int.tv_sec = interval / 1000; 
    505553  p_int.tv_usec = (interval % 1000) * 1000; 
    506   packet_len = sizeof(*icp) + PING_PAYLOAD_LEN; 
     554  icp_len = (check->target_family == AF_INET6) ? 
     555              sizeof(struct icmp6_hdr) : sizeof(struct icmp); 
     556  packet_len = icp_len + PING_PAYLOAD_LEN; 
    507557 
    508558  /* Prep holding spots for return info */ 
     
    523573 
    524574    icp = calloc(1,packet_len); 
    525     payload = (struct ping_payload *)(icp + 1); 
    526  
    527     icp->icmp_type = ICMP_ECHO; 
    528     icp->icmp_code = 0; 
    529     icp->icmp_cksum = 0; 
    530     icp->icmp_seq = htons(ci->seq++); 
    531     icp->icmp_id = (((vpsized_uint)self) & 0xffff); 
     575    payload = (struct ping_payload *)((char *)icp + icp_len); 
     576 
     577    if(check->target_family == AF_INET) { 
     578      struct icmp *icp4 = icp; 
     579      icp4->icmp_type = ICMP_ECHO; 
     580      icp4->icmp_code = 0; 
     581      icp4->icmp_cksum = 0; 
     582      icp4->icmp_seq = htons(ci->seq++); 
     583      icp4->icmp_id = (((vpsized_uint)self) & 0xffff); 
     584    } 
     585    else if(check->target_family == AF_INET6) { 
     586      struct icmp6_hdr *icp6 = icp; 
     587      icp6->icmp6_type = ICMP6_ECHO_REQUEST; 
     588      icp6->icmp6_code = 0; 
     589      icp6->icmp6_cksum = 0; 
     590      icp6->icmp6_seq = htons(ci->seq++); 
     591      icp6->icmp6_id = (((vpsized_uint)self) & 0xffff); 
     592    } 
    532593 
    533594    payload->addr_of_check = check; 
     
    543604    pcl->payload = icp; 
    544605    pcl->payload_len = packet_len; 
     606    pcl->icp_len = icp_len; 
    545607 
    546608    newe->closure = pcl; 
     
    617679  if(!nldeb) nldeb = noit_debug; 
    618680  eventer_name_callback("ping_icmp/timeout", ping_icmp_timeout); 
    619   eventer_name_callback("ping_icmp/handler", ping_icmp_handler); 
     681  eventer_name_callback("ping_icmp/handler", ping_icmp4_handler); 
     682  eventer_name_callback("ping_icmp6/handler", ping_icmp6_handler); 
    620683  eventer_name_callback("ping_icmp/send", ping_icmp_real_send); 
    621684  return 0;