The InspIRCd Project
Home | Developers | Wiki | Forums | Bug Tracker | SVN | Download | Blog | Stats
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

irc::sockets Namespace Reference

This namespace contains various protocol-independent helper classes. More...


Typedefs

typedef sockaddr_in insp_sockaddr
 insp_sockaddr for ipv4
typedef in_addr insp_inaddr
 insp_inaddr for ipv4

Functions

bool MatchCIDRBits (unsigned char *address, unsigned char *mask, unsigned int mask_bits)
 Match raw binary data using CIDR rules.
bool MatchCIDR (const char *address, const char *cidr_mask)
 Match CIDR, without matching username/nickname parts.
bool MatchCIDR (const char *address, const char *cidr_mask, bool match_with_username)
 Match CIDR, including an optional username/nickname part.
void Blocking (int s)
 Make a socket file descriptor a blocking socket.
void NonBlocking (int s)
 Make a socket file descriptor into a nonblocking socket.
int OpenTCPSocket (char *addr, int socktype=SOCK_STREAM)
 Create a new valid file descriptor using socket().
const char * insp_ntoa (insp_inaddr n)
 Convert an insp_inaddr into human readable form.
int insp_aton (const char *a, insp_inaddr *n)
 Convert a human-readable address into an insp_inaddr.


Detailed Description

This namespace contains various protocol-independent helper classes.

It also contains some types which are often used by the core and modules in place of inet_* functions and types.


Typedef Documentation

typedef struct in_addr irc::sockets::insp_inaddr
 

insp_inaddr for ipv4

Definition at line 84 of file socket.h.

typedef struct sockaddr_in irc::sockets::insp_sockaddr
 

insp_sockaddr for ipv4

Definition at line 81 of file socket.h.


Function Documentation

CoreExport void irc::sockets::Blocking int  s  ) 
 

Make a socket file descriptor a blocking socket.

Parameters:
s A valid file descriptor

Definition at line 298 of file socket.cpp.

00299 {
00300 #ifndef WIN32
00301         int flags = fcntl(s, F_GETFL, 0);
00302         fcntl(s, F_SETFL, flags ^ O_NONBLOCK);
00303 #else
00304         unsigned long opt = 0;
00305         ioctlsocket(s, FIONBIO, &opt);
00306 #endif
00307 }

CoreExport int irc::sockets::insp_aton const char *  a,
insp_inaddr n
 

Convert a human-readable address into an insp_inaddr.

Parameters:
a A human-readable address
n An insp_inaddr struct which the result will be copied into on success.
Returns:
This method will return a negative value if address does not contain a valid address family. 0 if the address is does not contain a valid string representing a valid network address. A positive value is returned if the network address was successfully converted.
or any other number upon failure.

Definition at line 563 of file socket.cpp.

References AF_FAMILY.

Referenced by DispatcherThread(), Resolver::Resolver(), and SQLConn::SendNotify().

00564 {
00565         return inet_pton(AF_FAMILY, a, n);
00566 }

CoreExport const char * irc::sockets::insp_ntoa insp_inaddr  n  ) 
 

Convert an insp_inaddr into human readable form.

Parameters:
n An insp_inaddr (IP address) structure
Returns:
A human-readable address. IPV6 addresses will be shortened to remove fields which are 0.

Definition at line 556 of file socket.cpp.

References AF_FAMILY.

Referenced by DNS::GetName().

00557 {
00558         static char buf[1024];
00559         inet_ntop(AF_FAMILY, &n, buf, sizeof(buf));
00560         return buf;
00561 }

CoreExport bool irc::sockets::MatchCIDR const char *  address,
const char *  cidr_mask,
bool  match_with_username
 

Match CIDR, including an optional username/nickname part.

This function will compare a human-readable address (plus optional username and nickname) against a human-readable CIDR mask, for example joe!bloggs@1.2.3.4 against *!bloggs@1.2.0.0/16. This method supports both IPV4 and IPV6 addresses.

Parameters:
address The human readable address, e.g. fred@1.2.3.4
cidr_mask The human readable mask, e.g. *@1.2.0.0/16
Returns:
True if the mask matches the address

Definition at line 164 of file socket.cpp.

References match(), MatchCIDR(), and MatchCIDRBits().

00165 {
00166         unsigned char addr_raw[16];
00167         unsigned char mask_raw[16];
00168         unsigned int bits = 0;
00169         char* mask = NULL;
00170 
00171         /* The caller is trying to match ident@<mask>/bits.
00172          * Chop off the ident@ portion, use match() on it
00173          * seperately.
00174          */
00175         if (match_with_username)
00176         {
00177                 /* Duplicate the strings, and try to find the position
00178                  * of the @ symbol in each */
00179                 char* address_dupe = strdup(address);
00180                 char* cidr_dupe = strdup(cidr_mask);
00181         
00182                 /* Use strchr not strrchr, because its going to be nearer to the left */
00183                 char* username_mask_pos = strrchr(cidr_dupe, '@');
00184                 char* username_addr_pos = strrchr(address_dupe, '@');
00185 
00186                 /* Both strings have an @ symbol in them */
00187                 if (username_mask_pos && username_addr_pos)
00188                 {
00189                         /* Zero out the location of the @ symbol */
00190                         *username_mask_pos = *username_addr_pos = 0;
00191 
00192                         /* Try and match() the strings before the @
00193                          * symbols, and recursively call MatchCIDR without
00194                          * username matching enabled to match the host part.
00195                          */
00196                         bool result = (match(address_dupe, cidr_dupe) && MatchCIDR(username_addr_pos + 1, username_mask_pos + 1, false));
00197 
00198                         /* Free the stuff we created */
00199                         free(address_dupe);
00200                         free(cidr_dupe);
00201 
00202                         /* Return a result */
00203                         return result;
00204                 }
00205                 else
00206                 {
00207                         /* One or both didnt have an @ in,
00208                          * just match as CIDR
00209                          */
00210                         free(address_dupe);
00211                         free(cidr_dupe);
00212                         mask = strdup(cidr_mask);
00213                 }
00214         }
00215         else
00216         {
00217                 /* Make a copy of the cidr mask string,
00218                  * we're going to change it
00219                  */
00220                 mask = strdup(cidr_mask);
00221         }
00222 
00223         in_addr  address_in4;
00224         in_addr  mask_in4;
00225 
00226 
00227         /* Use strrchr for this, its nearer to the right */
00228         char* bits_chars = strrchr(mask,'/');
00229 
00230         if (bits_chars)
00231         {
00232                 bits = atoi(bits_chars + 1);
00233                 *bits_chars = 0;
00234         }
00235         else
00236         {
00237                 /* No 'number of bits' field! */
00238                 free(mask);
00239                 return false;
00240         }
00241 
00242 #ifdef SUPPORT_IP6LINKS
00243         in6_addr address_in6;
00244         in6_addr mask_in6;
00245 
00246         if (inet_pton(AF_INET6, address, &address_in6) > 0)
00247         {
00248                 if (inet_pton(AF_INET6, mask, &mask_in6) > 0)
00249                 {
00250                         memcpy(&addr_raw, &address_in6.s6_addr, 16);
00251                         memcpy(&mask_raw, &mask_in6.s6_addr, 16);
00252 
00253                         if (bits > 128)
00254                                 bits = 128;
00255                 }
00256                 else
00257                 {
00258                         /* The address was valid ipv6, but the mask
00259                          * that goes with it wasnt.
00260                          */
00261                         free(mask);
00262                         return false;
00263                 }
00264         }
00265         else
00266 #endif
00267         if (inet_pton(AF_INET, address, &address_in4) > 0)
00268         {
00269                 if (inet_pton(AF_INET, mask, &mask_in4) > 0)
00270                 {
00271                         memcpy(&addr_raw, &address_in4.s_addr, 4);
00272                         memcpy(&mask_raw, &mask_in4.s_addr, 4);
00273 
00274                         if (bits > 32)
00275                                 bits = 32;
00276                 }
00277                 else
00278                 {
00279                         /* The address was valid ipv4,
00280                          * but the mask that went with it wasnt.
00281                          */
00282                         free(mask);
00283                         return false;
00284                 }
00285         }
00286         else
00287         {
00288                 /* The address was neither ipv4 or ipv6 */
00289                 free(mask);
00290                 return false;
00291         }
00292 
00293         /* Low-level-match the bits in the raw data */
00294         free(mask);
00295         return MatchCIDRBits(addr_raw, mask_raw, bits);
00296 }

CoreExport bool irc::sockets::MatchCIDR const char *  address,
const char *  cidr_mask
 

Match CIDR, without matching username/nickname parts.

This function will compare a human-readable address against a human- readable CIDR mask, for example 1.2.3.4 against 1.2.0.0/16. This method supports both IPV4 and IPV6 addresses.

Parameters:
address The human readable address, e.g. 1.2.3.4
cidr_mask The human readable mask, e.g. 1.2.0.0/16
Returns:
True if the mask matches the address

Definition at line 152 of file socket.cpp.

Referenced by match(), MatchCIDR(), and TreeSocket::OnIncomingConnection().

00153 {
00154         return MatchCIDR(address, cidr_mask, false);
00155 }

CoreExport bool irc::sockets::MatchCIDRBits unsigned char *  address,
unsigned char *  mask,
unsigned int  mask_bits
 

Match raw binary data using CIDR rules.

This function will use binary comparison to compare the two bit sequences, address and mask, up to mask_bits bits in size. If they match, it will return true.

Parameters:
address The whole address, of 4 or 16 bytes in length
mask The mask, from 1 to 16 bytes in length, anything from 1 to 128 bits of which is significant
mask_Bits How many bits of the mask parameter are significant for this comparison.
Returns:
True if the first mask_bits of address matches the first mask_bits of mask.

Definition at line 132 of file socket.cpp.

References inverted_bits.

Referenced by MatchCIDR().

00133 {
00134         unsigned int modulus = mask_bits % 8; /* Number of whole bytes in the mask */
00135         unsigned int divisor = mask_bits / 8; /* Remaining bits in the mask after whole bytes are dealt with */
00136 
00137         /* First compare the whole bytes, if they dont match, return false */
00138         if (memcmp(address, mask, divisor))
00139                 return false;
00140 
00141         /* Now if there are any remainder bits, we compare them with logic AND */
00142         if (modulus)
00143                 if ((address[divisor] & inverted_bits[modulus]) != (mask[divisor] & inverted_bits[modulus]))
00144                         /* If they dont match, return false */
00145                         return false;
00146 
00147         /* The address matches the mask, to mask_bits bits of mask */
00148         return true;
00149 }

CoreExport void irc::sockets::NonBlocking int  s  ) 
 

Make a socket file descriptor into a nonblocking socket.

Parameters:
s A valid file descriptor

Definition at line 309 of file socket.cpp.

Referenced by InspIRCd::BindSocket(), ListenSocket::HandleEvent(), IdentRequestSocket::IdentRequestSocket(), InspSocket::Poll(), and DNS::Rehash().

00310 {
00311 #ifndef WIN32
00312         int flags = fcntl(s, F_GETFL, 0);
00313         fcntl(s, F_SETFL, flags | O_NONBLOCK);
00314 #else
00315         unsigned long opt = 1;
00316         ioctlsocket(s, FIONBIO, &opt);
00317 #endif
00318 }

CoreExport int irc::sockets::OpenTCPSocket char *  addr,
int  socktype = SOCK_STREAM
 

Create a new valid file descriptor using socket().

Returns:
On return this function will return a value >= 0 for success, or a negative value upon failure (negative values are invalid file descriptors)

Definition at line 446 of file socket.cpp.

References ERROR.

Referenced by InspSocket::InspSocket(), ListenSocket::ListenSocket(), and DNS::Rehash().

00447 {
00448         int sockfd;
00449         int on = 1;
00450         struct linger linger = { 0 };
00451 #ifdef IPV6
00452         if (strchr(addr,':') || (!*addr))
00453                 sockfd = socket (PF_INET6, socktype, 0);
00454         else
00455                 sockfd = socket (PF_INET, socktype, 0);
00456         if (sockfd < 0)
00457 #else
00458         if ((sockfd = socket (PF_INET, socktype, 0)) < 0)
00459 #endif
00460         {
00461                 return ERROR;
00462         }
00463         else
00464         {
00465                 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
00466                 /* This is BSD compatible, setting l_onoff to 0 is *NOT* http://web.irc.org/mla/ircd-dev/msg02259.html */
00467                 linger.l_onoff = 1;
00468                 linger.l_linger = 1;
00469                 setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char*)&linger,sizeof(linger));
00470                 return (sockfd);
00471         }
00472 }