Logo Search packages:      
Sourcecode: ldapdns version File versions  Download package

ip4.h

/* these functions are useful for dealing with IPv4 */
#ifndef __ip4_h
#define __ip4_h

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>

#include "str.h"
#include "mem.h"

#ifndef IP_LEN
#define IP_LEN    4
#endif

static int inline ipv4_null(unsigned char *ip)
{
      int i;
      for (i = 0; ip[i] == 0 && i < 4; i++);
      return i == 4 ? 1 : 0;
}
static int inline ipv4_scan(const char *str, unsigned char ip[4])
{
      int p, v;

      ip[0] = ip[1] = ip[2] = ip[3] = 0;
      for (p = v = 0; *str && p < 4;) {
            switch (*str) {
            case '0': v *= 10; break;
            case '1': v *= 10; v ++; break;
            case '2': v *= 10; v += 2; break;
            case '3': v *= 10; v += 3; break;
            case '4': v *= 10; v += 4; break;
            case '5': v *= 10; v += 5; break;
            case '6': v *= 10; v += 6; break;
            case '7': v *= 10; v += 7; break;
            case '8': v *= 10; v += 8; break;
            case '9': v *= 10; v += 9; break;
            case '.': ip[p] = v; v = 0; p++; break;
            default: return 0;
            };
            str++;
      }
      if (p == 4) return 0;
      ip[p] = v;
      return 4;
}
static int inline ipv4_in_subnet(unsigned char cidr[8], unsigned char ip[4])
{
      register int i;
      if (ipv4_null(cidr)) return 1;
      for (i = 0; i < 4; i++) {
            if (cidr[i] != (ip[i] & cidr[4+i]))
                  return 0;
      }
      return 1;
}
static int inline ipv4_cidr(char *str, unsigned char cidr[8])
{
      int r;
      str_t s;
      char *p;

      /* like ipv4_scan but parses a CIDR number */
      str_init(s);
      str_copy(s, str);
      for (p = str(s); *p && *p != '/'; p++);
      if (*p == '/') {
            *p = 0; p++;
            if (!ipv4_scan(str(s), cidr)) {
                  mem_free(str(s));
                  return 0;
            }
            for (r = 0; p[r]; r++)
                  if (p[r] == '.' && ipv4_scan(p, cidr+4)) {
                        /* form of IN/IN */
                        mem_free(str(s));
                        return 8;
                  }
            /* must be in cidr notation (really) */
            r = atoi(p);
            if (r == -1) {
                  mem_free(str(s));
                  return 0;
            }
            cidr[4] = cidr[5] = cidr[6] = cidr[7] = 0xFF;
            if (r < 8) {
                  cidr[4] = (0xFF << (8 - r));
                  cidr[5] = cidr[6] = cidr[7] = 0x00;
            } else if (r < 16) {
                  cidr[5] = (0xFF << (16 - r));
                  cidr[6] = cidr[7] = 0x00;
            } else if (r < 24) {
                  cidr[6] = (0xFF << (24 - r));
                  cidr[7] = 0x00;
            } else {
                  cidr[7] = (0xFF << (32 - r));
            }
            mem_free(str(s));
            return 8;
      } else {
            mem_free(str(s));
            return 0;
      }
}
static int inline socket_bind4(int fd, unsigned char ip[4], int port)
{
      struct sockaddr_in sin;

      memzero(&sin, sizeof(sin));

      sin.sin_family = PF_INET;
      /* Clib */
      sin.sin_port = htons(port);
      memcpy(&sin.sin_addr, ip, 4);

      return bind(fd, (struct sockaddr *)&sin, sizeof(sin));
}
static int inline socket_bind4_reuse(int fd, unsigned char ip[4], int port)
{
      int opt = 1;
      setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
      return socket_bind4(fd, ip, port);
}
static int inline socket_peer4(int fd, unsigned char ip[4], int *port)
{
      struct sockaddr_in sin;
      int silen;

      memzero(&sin, sizeof(sin));

      silen = sizeof(sin);
      sin.sin_family = PF_INET;
      if (getpeername(fd, (struct sockaddr *)&sin, (int *)&silen) == -1) {
            return 0;
      }

      if (sin.sin_family != PF_INET)
            return 0;

      memcpy(ip, &sin.sin_addr, 4);
      *port = ntohs(sin.sin_port);
      return 1;
}
static int inline socket_local4(int fd, unsigned char ip[4], int *port)
{
      struct sockaddr_in sin;
      int silen;

      memzero(&sin, sizeof(sin));

      silen = sizeof(sin);
      sin.sin_family = PF_INET;
      if (getsockname(fd, (struct sockaddr *)&sin, (int *)&silen) == -1) {
            return 0;
      }

      if (sin.sin_family != PF_INET)
            return 0;

      memcpy(ip, &sin.sin_addr, 4);
      *port = ntohs(sin.sin_port);
      return 1;
}

static int inline socket_tcp4(void)
{
      int fd;

      fd = socket(PF_INET, SOCK_STREAM, 0);
      if (fd == -1) return -1;
      if (ndelay_on(fd) == -1) { close(fd); return -1; }
      return fd;
}
static int inline socket_udp4(void)
{
      int fd;

      fd = socket(PF_INET, SOCK_DGRAM, 0);
      if (fd == -1) return -1;
      if (ndelay_on(fd) == -1) { close(fd); return -1; }
      return fd;
}
static int inline socket_accept4(int s, unsigned char ip[4], int *port)
{
      struct sockaddr_in sa;
      int dummy = sizeof sa;
      int r;

      memzero(&sa, sizeof(sa));

      r = accept(s, (struct sockaddr *)&sa, &dummy);
      if (r == -1) return -1;

      memcpy(ip, &sa.sin_addr, 4);
      *port = ntohs(sa.sin_port);

      return r;
}
static int inline socket_recv4(int s, char *buf, int len, unsigned char ip[4], int *port)
{
      struct sockaddr_in sa;
      int dummy = sizeof sa;
      int r;

      memzero(&sa, sizeof(sa));

      r = recvfrom(s, buf, len, 0, (struct sockaddr *)&sa, &dummy);
      if (r == -1) return -1;

      memcpy(ip, &sa.sin_addr, 4);
      *port = ntohs(sa.sin_port);

      return r;
}
static int inline socket_send4(int s, const char *buf, int len, const unsigned char ip[4], int port)
{
      struct sockaddr_in sa;

      memzero(&sa, sizeof(sa));

      sa.sin_family = PF_INET;
      sa.sin_port = htons(port);
      memcpy(&sa.sin_addr, ip, 4);

      return sendto(s, buf, len, 0, (struct sockaddr *)&sa, sizeof(sa));
}

#endif

Generated by  Doxygen 1.6.0   Back to index