NSIS-ka
A free C++ implementation of NSIS protocols

Changeset 4091


Ignore:
Timestamp:
Jul 13, 2009, 12:16:01 PM (8 years ago)
Author:
stud-lenk
Message:

Rework setup of ancillary data for sendmsg()

  • swap function set_ancillary_data() out to a separate file cmsghdr_util.cpp
  • extend set_ancillary_data() to accept additional outgoing interface and hop limit information
  • make use of the new set_ancillary_data() by TPQueryEncap aswell as by TPoverUDP

Additionally fix a memory leak (TPoverUDP::udpsend() was not freeing msg->msg_control).

Location:
protlib/branches/20080820-configpar
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • protlib/branches/20080820-configpar/include/tp_queryencap.h

    r2718 r4091  
    179179  void setup_socket_ipv4(int sockfd, int hop_limit, int rao);
    180180  void setup_socket_ipv6(int sockfd, int hop_limit, int rao);
    181   void set_ancillary_data(struct msghdr *msg, int rao);
    182181 
    183182  /// ConnectionMap instance for keeping track of all existing connections
  • protlib/branches/20080820-configpar/src/Makefile

    r3822 r4091  
    105105TP_QUERY_ENCAP_OBJ= tp_queryencap.o
    106106
    107 PROTLIB_OBJS    = address.o ie.o tp.o tp_over_tcp.o \
    108                   tp_over_tls_tcp.o tp_over_udp.o $(TP_QUERY_ENCAP_OBJ) tp_over_uds.o \
     107PROTLIB_OBJS    = address.o ie.o tp.o tp_over_tcp.o tp_over_tls_tcp.o \
     108                  cmsghdr_util.o tp_over_udp.o $(TP_QUERY_ENCAP_OBJ) tp_over_uds.o \
    109109                  $(TP_SCTPOBJ) connectionmap.o connectionmap_uds.o queuemanager.o fqueue.o \
    110110                  timer.o timer_module.o logfile.o fqueue.o protlib_types.o threads.o \
     
    242242#compile rules
    243243
     244cmsghdr_util.o: cmsghdr_util.cpp cmsghdr_util.h
     245        $(RM) $@
     246        $(CPP) $(PROTLIB_CXXFLAGS) $(CFLAGS) $(CLINK) $@ $(INCLUDE) $<
     247
    244248%.o:            %.cpp
    245249                $(RM) $@
  • protlib/branches/20080820-configpar/src/tp_over_udp.cpp

    r3822 r4091  
    5555#include "setuid.h"
    5656#include "logfile.h"
     57#include "cmsghdr_util.h"
    5758#include "linux/netfilter.h"
    5859
     
    144145  struct msghdr header;
    145146
    146   // pointer for ancillary data
    147   struct cmsghdr *ancillary = NULL;
    148          
    149147  // iovec for sendmsg
    150148  struct iovec iov;
     
    160158  dest_address.sin6_scope_id = 0;
    161159
     160  // control options for sendmsg
     161  int hop_limit = ( addr->get_ip_ttl() ? addr->get_ip_ttl() : -1 );
     162  if ( hop_limit != -1 )
     163    DLog(tpparam.name, "Setting IP hop limit to " << hop_limit);
     164
     165  int rao = ( addr->rao_present() ? addr->get_rao() : -1 );
     166  if ( rao != -1 )
     167    DLog(tpparam.name, "Setting IP RAO to " << rao);
     168
     169  uint16_t oif = addr->get_if_index();
     170  if ( oif != 0 )
     171    DLog(tpparam.name, "Setting outgoing interface index to " << oif);
     172
    162173  // fill msghdr
    163174  header.msg_iov = &iov;
     
    168179  header.msg_controllen=0;
    169180
    170 
    171   // pktinfo
    172   in6_pktinfo pktinfo;
    173 
    174   //addr->set_if_index(1);
    175 
    176 
    177   // we have to add up to 2 ancillary data objects (for interface and hop limit)
    178 
    179   uint32 buflength = 0;
    180   if (addr->get_if_index()) {
    181     buflength = CMSG_SPACE(sizeof(pktinfo));
    182     //cout << "PKTINFO data object, total buffer size: " << buflength << "byte" << endl;
    183   }
    184 
    185   int hlim = addr->get_ip_ttl();
    186 
    187   if (hlim) {
    188     buflength = buflength + CMSG_SPACE(sizeof(int));
    189     //cout << "HOPLIMIT data object, total buffer size: " << buflength << "byte" << endl;
    190   }
    191   // create the buffer
    192   if ((addr->get_if_index()) || hlim) {
    193     header.msg_control = malloc(buflength);
    194     if (header.msg_control == 0)
    195       ERRCLog(tpparam.name, thisproc << " malloc failed for ancillary data of size " << buflength);
    196   }
    197 
    198   // are we to set the outgoing interface?
    199   if (addr->get_if_index()) {
    200 
    201     DLog(tpparam.name, thisproc << " UDP send via Interface " << addr->get_if_index() << " requested.");
    202 
    203     // first cmsghdr at beginning of buffer
    204     ancillary = (cmsghdr*) header.msg_control;
    205          
    206     ancillary->cmsg_level=IPPROTO_IPV6;
    207     ancillary->cmsg_type=IPV6_PKTINFO;
    208     ancillary->cmsg_len=CMSG_LEN(sizeof(pktinfo));
    209          
    210     //cout << "Set up properties of ancillary data object 1" << endl;
    211 
    212     pktinfo.ipi6_addr = in6addr_any;
    213     pktinfo.ipi6_ifindex = addr->get_if_index();
    214 
    215     memcpy (CMSG_DATA(ancillary), &pktinfo, sizeof(pktinfo));
    216  
    217     //cout << "Set up data of ancillary data object 1" << endl;
    218 
    219     // update msghdr controllen
    220     header.msg_controllen = CMSG_SPACE(sizeof(pktinfo));
    221          
    222   }
    223 
    224   // should we set an explicit Hop Limit?
    225   if (hlim) {
    226     DLog(tpparam.name, thisproc << " UDP send with IP TTL of " << hlim << " requested.");
    227 
    228     // second cmsghdr after first one
    229     cmsghdr* ancillary2 = NULL;
    230 
    231     if (ancillary) {
    232       ancillary2 = (cmsghdr*) (ancillary + CMSG_SPACE(sizeof(pktinfo)));
    233     } else {
    234       ancillary2 = (cmsghdr*) header.msg_control;
    235     }
    236 
    237     ancillary2->cmsg_level=IPPROTO_IPV6;
    238     ancillary2->cmsg_type=IPV6_HOPLIMIT;
    239     ancillary2->cmsg_len = CMSG_LEN(sizeof(int));
    240 
    241     memcpy(CMSG_DATA(ancillary2), &hlim, sizeof(int));
    242  
    243     // update msghdr controllen
    244     header.msg_controllen = header.msg_controllen + ancillary2->cmsg_len;
    245 
    246   }
     181  // fill msghdr.msg_control
     182  util::set_ancillary_data(&header, rao, oif, hop_limit);
    247183
    248184#ifndef _NO_LOGGING
     
    269205  DLog(tpparam.name, "SEND to " << *addr);
    270206  ret= sendmsg(master_listener_socket,&header,MSG_DONTWAIT); 
     207
     208  // free ancilliary data allocated by protlib::util::set_ancillary_data()
     209  free(header.msg_control);
     210  header.msg_control = NULL; // ... just in case
    271211
    272212  if (ret<0)
  • protlib/branches/20080820-configpar/src/tp_queryencap.cpp

    r4090 r4091  
    5858#include "queuemanager.h"
    5959#include "logfile.h"
     60#include "cmsghdr_util.h"
    6061#include "linux/netfilter.h"
    6162
     
    191192
    192193
    193 /*
    194  * Definitions for the IPv6 Router Alert Option, see RFC-2711.
    195  */
    196 static const uint8_t IP6_RAO_OPT_TYPE           = 0x05; // hop-by-hop opt. type
    197 static const uint8_t IP6_RAO_OPT_LEN            = 2;
    198 static const uint8_t IP6_RAO_OPT_ALIGN          = 2;    // 2n + 0 alignment
    199 
    200 #ifdef HAS_RFC2292
    201 static const uint8_t IP6_RAO_OPT_MULTX          = 2;    // 2n + 0 alignment
    202 static const uint8_t IP6_RAO_OPT_OFFSETY        = 0;
    203 #endif
    204 
    205 struct ip6_rao_opt {
    206         uint8_t         ip6_rao_opt_type;
    207         uint8_t         ip6_rao_opt_len;
    208         uint16_t        ip6_rao_opt_val;
    209 };
    210 
    211 
    212 /**
    213  * Activate the router alert option in the given msghdr structure.
    214  *
    215  * This sets the msg_control and msg_controllen fields of the msghdr structure.
    216  * Note that the msg_control member points to allocated memory which you have
    217  * to free yourself.
    218  *
    219  * @param msg the msghdr structure for sendmsg(2)
    220  * @param rao the RAO in host byte order (a 16 bit value, or -1)
    221  */
    222 void
    223 TPqueryEncap::set_ancillary_data(struct msghdr *msg, int rao) {
    224   const char *const methodname= "TPqueryEncap::set_ancillary_data()";
    225 
    226   struct cmsghdr *cmsgptr= NULL;
    227 
    228 #ifdef HAS_RFC2292
    229         struct ip6_rao_opt opt_rao;
    230 #else
    231         int currentlen;
    232         socklen_t extlen;
    233         uint16_t val;
    234         void *databuf, *extbuf;
    235 #endif
    236 
    237         assert( msg->msg_control == NULL );
    238         assert( msg->msg_controllen == 0 );
    239 
    240         if (rao == -1)
    241                 return;
    242 
    243 #ifdef HAS_RFC2292
    244         /* We have to free this later! */
    245         msg->msg_control = malloc( inet6_option_space(sizeof opt_rao) );
    246         assert( msg->msg_control != NULL );
    247 
    248         inet6_option_init(msg->msg_control, &cmsgptr, IPV6_HOPOPTS);
    249 
    250         opt_rao.ip6_rao_opt_type = IP6_RAO_OPT_TYPE;
    251         opt_rao.ip6_rao_opt_len = IP6_RAO_OPT_LEN;
    252         opt_rao.ip6_rao_opt_val = htons(rao);
    253 
    254         inet6_option_append(cmsgptr, &opt_rao.ip6_rao_opt_type,
    255                                 IP6_RAO_OPT_MULTX, IP6_RAO_OPT_OFFSETY);
    256 
    257         msg->msg_controllen = cmsgptr->cmsg_len;
    258 #else
    259 
    260         /* Quote from RFC 3542:
    261          * All the Hop-by-Hop options must be specified by a single ancillary
    262          * data object.  The cmsg_level member is set to IPPROTO_IPV6 and the
    263          * cmsg_type member is set to IPV6_HOPOPTS.  The option is normally
    264          * constructed using the inet6_opt_init(), inet6_opt_append(),
    265          * inet6_opt_finish(), and inet6_opt_set_val() functions, described in
    266          * Section 10.
    267          */
    268 
    269 
    270         // Calculate the required memory space first
    271         currentlen = inet6_opt_init(NULL, 0);
    272         if (currentlen == -1)
    273         {
    274           ERRCLog(methodname, "Failure while calculating Hop-by-Hop Router Alert Option, inet6_opt_init()");
    275           return;
    276         }
    277         // RFC 2711:
    278         //    The router alert option has the following format:
    279         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    280         // |0 0 0|0 0 1 0 1|0 0 0 0 0 0 1 0|        Value (2 octets)       |
    281         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    282         //                  length = 2
    283         //
    284         // Alignment requirement: 2n+0
    285         //
    286         // Hbh-Extension Header for Router Alert should look like this:
    287         //
    288         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    289         // |Next Header=UDP| Hdr Ext Len=0 | Option Type=5 |Opt Data Len=2 |
    290         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    291         // |        Value (2 octets)       | Option Type=1 |Opt Data Len=0 | (PadN, 2 bytes)
    292         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    293         // in Hex: 0x11 00 05 02 XX XX 01 00 (if next header is UDP)
    294         //
    295         // or like this:
    296         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    297         // |Next Header=UDP| Hdr Ext Len=0 | Option Type=1 |Opt Data Len=0 | (PadN, 2 bytes)
    298         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    299         // | Option Type=1 |Opt Data Len=0 |      Value (2 octets)         |
    300         // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    301         // in Hex: 0x11 00 01 00 05 02 XX XX (if next header is UDP)
    302 
    303         currentlen = inet6_opt_append(NULL, 0, currentlen,
    304                                       IP6_RAO_OPT_TYPE,
    305                                       IP6_RAO_OPT_LEN,
    306                                       IP6_RAO_OPT_ALIGN, NULL);
    307         if (currentlen == -1)
    308         {
    309           ERRCLog(methodname, "Failure while calculating Hop-by-Hop Router Alert Option, does not fit into extension header");
    310           return;
    311         }
    312         currentlen = inet6_opt_finish(NULL, 0, currentlen);
    313         if (currentlen == -1)
    314         {
    315           ERRCLog(methodname, "Failure while calculating Hop-by-Hop Router Alert Option, inet6_opt_finish()");
    316           return;
    317         }
    318 
    319         // now allocate the csmg stuff
    320         // extlen is the length of the header extension in bytes
    321         extlen = currentlen;
    322         // allocate space for the ancillary data structure
    323         int cmsgspace= CMSG_SPACE(extlen);
    324         cmsgptr= static_cast<cmsghdr*>( malloc(cmsgspace) );
    325         memset(cmsgptr, 0, cmsgspace);
    326 
    327         assert(cmsgptr != NULL);
    328 
    329         cmsgptr->cmsg_level = IPPROTO_IPV6;
    330         cmsgptr->cmsg_type = IPV6_HOPOPTS;
    331         cmsgptr->cmsg_len = CMSG_LEN(extlen);
    332         extbuf = CMSG_DATA(cmsgptr);
    333 
    334         assert(extbuf != NULL);
    335 
    336         //DLog(methodname, "Hop-by-Hop Router Alert Option, BufferSize: " << extlen);
    337 
    338         // Quoting RFC 2460:
    339         // Hdr Ext Len          8-bit unsigned integer.  Length of the Hop-by-
    340         //                      Hop Options header in 8-octet units, not
    341         //                      including the first 8 octets.
    342 
    343         currentlen = inet6_opt_init(extbuf, extlen);
    344         if (currentlen == -1) {
    345           ERRCLog(methodname, "Failure while setting Hop-by-Hop Router Alert Option, inet6_opt_init()");
    346           free(extbuf);
    347           return;
    348         }
    349         // inet6_opt_init initializes the value wrongly (glibc2.6.1):
    350         // it divides extlen by 8, but passsing an extlen of 0 is not possible
    351         // so we must fix the setting now
    352         struct ip6_hbh *extp = reinterpret_cast<struct ip6_hbh *>(extbuf);
    353         // inet6_opt_init did already some sanity checks (extlen is multiple of 8)
    354         extp->ip6h_len= (extlen / 8) - 1; // should be zero then, indicating a length of 8 bytes
    355 
    356         currentlen = inet6_opt_append(extbuf, extlen, currentlen,
    357             IP6_RAO_OPT_TYPE, IP6_RAO_OPT_LEN, IP6_RAO_OPT_ALIGN,
    358             &databuf);
    359         if (currentlen == -1) {
    360           ERRCLog(methodname, "Failure while setting Hop-by-Hop Router Alert Option, does not fit into extension header");
    361           free(extbuf);
    362           return;
    363         }
    364 
    365         val = htons(rao);
    366         (void)inet6_opt_set_val(databuf, 0, &val, sizeof(val));
    367 
    368         currentlen = inet6_opt_finish(extbuf, extlen, currentlen);
    369         if (currentlen == -1) {
    370           ERRCLog(methodname, "Failure while setting Hop-by-Hop Router Alert Option, inet6_opt_finish()");
    371           free(extbuf);
    372           return;
    373         }
    374        
    375         msg->msg_control = cmsgptr;
    376         msg->msg_controllen = cmsgspace;
    377 #endif
    378 
    379         NetMsg tmpmsg( (uchar*) msg->msg_control, (uint32) msg->msg_controllen, true );
    380 
    381         //ostringstream out;
    382         //tmpmsg.hexdump(out);
    383         //DLog(methodname, "Hop-by-Hop Router Alert Option, Cmsg Space:" << msg->msg_controllen << " cmsglen:" << cmsgptr->cmsg_len << " Buffer Contents: " << out.str());
    384 
    385 }
    386 
    387 
    388 
    389194/**
    390195 * Send the given NetMsg via UDP to the given address.
     
    417222    DLog(tpparam.name, "Setting IP RAO to " << rao);
    418223
     224  uint16_t oif = addr->get_if_index();
     225  if ( oif != 0 )
     226    DLog(tpparam.name, "Setting outgoing interface index to " << oif);
     227
    419228  try {
    420229    check_send_args(*netmsg, *addr);
     
    474283
    475284  // this sets msg.msg_control and msg.msg_controllen
    476   set_ancillary_data(&msg, rao);
     285  util::set_ancillary_data(&msg, rao, oif, hop_limit);
    477286
    478287  /*
     
    480289   * so we can finally send the message.
    481290   */
    482 
    483   // TODO: Setting the outgoing interface is currently unimplemented,
    484   //       but I don't think it worked with r1816 or earlier.
    485 
    486291
    487292  // return code will be checked below
Note: See TracChangeset for help on using the changeset viewer.