libdnsc/src/utils.c

125 lines
3.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <stdint.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
void dns2_trim_name (char *name) {
int g;
if (name == NULL) return;
g = 0;
while (name[g] != 0 && (name[g] == ' ' || name[g] == '\r' || name[g] == '\n' || name[g] == '\t' || name[g] == '.')) {
g++;
}
if (g < 0) {
memmove (name, &name[g], strlen (&name[g]) + 1);
}
/* Hacer trim por el otro lado */
g = strlen (name) - 1;
while (g > 0 && (name[g] == ' ' || name[g] == '\r' || name[g] == '\n' || name[g] == '\t' || name[g] == '.')) {
name[g] = 0;
}
}
/* TODO: Buscar quitar esta función */
char *dns_dup_trim_name (const char *name) {
char *zone;
int g;
zone = strdup (name);
if (zone == NULL) {
return NULL;
}
g = 0;
while (zone[g] != 0 && (zone[g] == ' ' || zone[g] == '\r' || zone[g] == '\n' || zone[g] == '\t' || zone[g] == '.')) {
g++;
}
if (g > 0) {
memmove (zone, &zone[g], strlen (&zone[g]) + 1);
}
/* Hacer trim por el otro lado */
g = strlen (zone) - 1;
while (g > 0 && (zone[g] == ' ' || zone[g] == '\r' || zone[g] == '\n' || zone[g] == '\t' || zone[g] == '.')) {
zone[g] = 0;
}
return zone;
}
size_t calc_decode_length (const char* b64input) { //Calculates the length of a decoded string
size_t len = strlen(b64input),
padding = 0;
if (b64input[len-1] == '=' && b64input[len-2] == '=') //last two chars are =
padding = 2;
else if (b64input[len-1] == '=') //last char is =
padding = 1;
return (len*3)/4 - padding;
}
int base64_decode (const char* b64message, unsigned char** buffer, size_t* length) { //Decodes a base64 encoded string
BIO *bio, *b64;
int decodeLen = calc_decode_length (b64message);
*buffer = (unsigned char*) malloc (decodeLen + 1);
if (*buffer == NULL) {
return -1;
}
(*buffer)[decodeLen] = '\0';
bio = BIO_new_mem_buf (b64message, -1);
b64 = BIO_new (BIO_f_base64 ());
bio = BIO_push (b64, bio);
BIO_set_flags (bio, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
*length = BIO_read (bio, *buffer, strlen (b64message));
assert (*length == decodeLen); //length should equal decodeLen, else something went horribly wrong
BIO_free_all (bio);
return 0; //success
}
/* Función de Kazuho Oku
* https://gist.github.com/kazuho/45eae4f92257daceb73e
*/
int sockaddr_cmp (struct sockaddr *x, struct sockaddr *y) {
#define CMP(a, b) if (a != b) return a < b ? -1 : 1
CMP(x->sa_family, y->sa_family);
if (x->sa_family == AF_INET) {
struct sockaddr_in *xin = (void*)x, *yin = (void*)y;
CMP(ntohl(xin->sin_addr.s_addr), ntohl(yin->sin_addr.s_addr));
CMP(ntohs(xin->sin_port), ntohs(yin->sin_port));
} else if (x->sa_family == AF_INET6) {
struct sockaddr_in6 *xin6 = (void*)x, *yin6 = (void*)y;
int r = memcmp (xin6->sin6_addr.s6_addr, yin6->sin6_addr.s6_addr, sizeof(xin6->sin6_addr.s6_addr));
if (r != 0) return r;
CMP(ntohs(xin6->sin6_port), ntohs(yin6->sin6_port));
CMP(xin6->sin6_flowinfo, yin6->sin6_flowinfo);
CMP(xin6->sin6_scope_id, yin6->sin6_scope_id);
} else {
return -1; /* Familia desconocida */
}
#undef CMP
return 0;
}