mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add basic getaddrinfo(3) support for localhost ports.
This commit is contained in:
parent
7c3d9bf2b9
commit
697d52b88a
2 changed files with 97 additions and 12 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2013, 2016.
|
||||||
|
|
||||||
This file is part of the Sortix C Library.
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
@ -23,12 +23,16 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
extern "C" void freeaddrinfo(struct addrinfo*)
|
extern "C" void freeaddrinfo(struct addrinfo* ai)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s is not implemented, aborting.\n", __func__);
|
while ( ai )
|
||||||
abort();
|
{
|
||||||
|
struct addrinfo* todelete = ai;
|
||||||
|
ai = ai->ai_next;
|
||||||
|
free(todelete->ai_addr);
|
||||||
|
free(todelete->ai_canonname);
|
||||||
|
free(todelete);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2013, 2015.
|
Copyright(C) Jonas 'Sortie' Termansen 2013, 2015, 2016.
|
||||||
|
|
||||||
This file is part of the Sortix C Library.
|
This file is part of the Sortix C Library.
|
||||||
|
|
||||||
|
@ -22,14 +22,95 @@
|
||||||
|
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
extern "C" int getaddrinfo(const char* restrict, const char* restrict,
|
static bool linkaddrinfo(struct addrinfo** restrict* res_ptr,
|
||||||
const struct addrinfo* restrict,
|
const struct addrinfo* restrict templ)
|
||||||
struct addrinfo** restrict)
|
|
||||||
{
|
{
|
||||||
|
struct addrinfo* link = (struct addrinfo*) calloc(1, sizeof(struct addrinfo));
|
||||||
|
if ( !link )
|
||||||
|
return false;
|
||||||
|
link->ai_flags = templ->ai_flags;
|
||||||
|
link->ai_family = templ->ai_family;
|
||||||
|
link->ai_socktype = templ->ai_socktype;
|
||||||
|
link->ai_protocol = templ->ai_protocol;
|
||||||
|
link->ai_addrlen = templ->ai_addrlen;
|
||||||
|
link->ai_addr = (struct sockaddr*) malloc(templ->ai_addrlen);
|
||||||
|
if ( !link->ai_addr )
|
||||||
|
return free(link), false;
|
||||||
|
memcpy(link->ai_addr, templ->ai_addr, templ->ai_addrlen);
|
||||||
|
link->ai_canonname = templ->ai_canonname ? strdup(templ->ai_canonname) : NULL;
|
||||||
|
if ( templ->ai_canonname && !link->ai_canonname )
|
||||||
|
return free(link), free(link->ai_addr), false;
|
||||||
|
**res_ptr = link;
|
||||||
|
*res_ptr = &link->ai_next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int getaddrinfo(const char* restrict node,
|
||||||
|
const char* restrict servname,
|
||||||
|
const struct addrinfo* restrict hints,
|
||||||
|
struct addrinfo** restrict res)
|
||||||
|
{
|
||||||
|
struct addrinfo hints_def;
|
||||||
|
if ( !hints )
|
||||||
|
{
|
||||||
|
memset(&hints_def, 0, sizeof(hints_def));
|
||||||
|
hints_def.ai_family = AF_UNSPEC;
|
||||||
|
hints = &hints_def;
|
||||||
|
}
|
||||||
|
|
||||||
|
int socktype = hints->ai_socktype;
|
||||||
|
if ( socktype == 0 )
|
||||||
|
socktype = SOCK_STREAM;
|
||||||
|
|
||||||
|
in_port_t port = 0;
|
||||||
|
if ( servname )
|
||||||
|
{
|
||||||
|
if ( isspace((unsigned char) servname[0]) )
|
||||||
|
return EAI_SERVICE;
|
||||||
|
const char* end;
|
||||||
|
long portl = strtol(servname, (char**) &end, 10);
|
||||||
|
if ( end[0] )
|
||||||
|
return EAI_SERVICE;
|
||||||
|
if ( (in_port_t) portl != portl )
|
||||||
|
return EAI_SERVICE;
|
||||||
|
port = portl;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct addrinfo** res_orig = res;
|
||||||
|
*res = NULL;
|
||||||
|
|
||||||
|
if ( !node )
|
||||||
|
{
|
||||||
|
bool any = false;
|
||||||
|
if ( hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET )
|
||||||
|
{
|
||||||
|
any = true;
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
memset(&sin, 0, sizeof(sin));
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
sin.sin_port = htons(port);
|
||||||
|
memcpy(&sin.sin_addr, "\x7F\x00\x00\x01", 4);
|
||||||
|
struct addrinfo templ;
|
||||||
|
memset(&templ, 0, sizeof(templ));
|
||||||
|
templ.ai_family = sin.sin_family;
|
||||||
|
templ.ai_socktype = socktype;
|
||||||
|
templ.ai_protocol = hints->ai_protocol;
|
||||||
|
templ.ai_addrlen = sizeof(sin);
|
||||||
|
templ.ai_addr = (struct sockaddr*) &sin;
|
||||||
|
if ( !linkaddrinfo(&res, &templ) )
|
||||||
|
return freeaddrinfo(*res_orig), EAI_MEMORY;
|
||||||
|
}
|
||||||
|
if ( any )
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return EAI_NONAME;
|
return EAI_NONAME;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue