Commit 07eb658a authored by Paul Sajna's avatar Paul Sajna Committed by jD91mZM2
Browse files

Netdb

parent 3dbf9f87
......@@ -10,6 +10,7 @@ pub mod fnmatch;
pub mod grp;
pub mod inttypes;
pub mod locale;
pub mod netdb;
pub mod netinet_in;
//pub mod pthread;
pub mod pwd;
......
sys_includes = ["sys/socket.h", "netinet/in.h"]
include_guard = "_NETDB_H"
language = "C"
style = "Tag"
[enum]
prefix_with_name = true
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use alloc::String;
use alloc::Vec;
#[derive(Clone, Debug)]
pub struct DnsAnswer {
pub name: String,
pub a_type: u16,
pub a_class: u16,
pub ttl_a: u16,
pub ttl_b: u16,
pub data: Vec<u8>
}
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use self::answer::DnsAnswer;
pub use self::query::DnsQuery;
use core::slice;
use core::u16;
use alloc::String;
use alloc::Vec;
mod answer;
mod query;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
#[repr(packed)]
pub struct n16 {
inner: u16
}
impl n16 {
pub fn as_bytes(&self) -> &[u8] {
unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) }
}
pub fn from_bytes(bytes: &[u8]) -> Self {
n16 {
inner: unsafe { slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len()/2)[0] }
}
}
}
impl From<u16> for n16 {
fn from(value: u16) -> Self {
n16 {
inner: value.to_be()
}
}
}
impl From<n16> for u16 {
fn from(value: n16) -> Self {
u16::from_be(value.inner)
}
}
#[derive(Clone, Debug)]
pub struct Dns {
pub transaction_id: u16,
pub flags: u16,
pub queries: Vec<DnsQuery>,
pub answers: Vec<DnsAnswer>
}
impl Dns {
pub fn compile(&self) -> Vec<u8> {
let mut data = Vec::new();
macro_rules! push_u8 {
($value:expr) => {
data.push($value);
};
};
macro_rules! push_n16 {
($value:expr) => {
data.extend_from_slice(n16::from($value).as_bytes());
};
};
push_n16!(self.transaction_id);
push_n16!(self.flags);
push_n16!(self.queries.len() as u16);
push_n16!(self.answers.len() as u16);
push_n16!(0);
push_n16!(0);
for query in self.queries.iter() {
for part in query.name.split('.') {
push_u8!(part.len() as u8);
data.extend_from_slice(part.as_bytes());
}
push_u8!(0);
push_n16!(query.q_type);
push_n16!(query.q_class);
}
data
}
pub fn parse(data: &[u8]) -> Result<Self, String> {
let name_ind = 0b11000000;
let mut i = 0;
macro_rules! pop_u8 {
() => {
{
i += 1;
if i > data.len() {
return Err(format!("{}: {}: pop_u8", file!(), line!()));
}
data[i - 1]
}
};
};
macro_rules! pop_n16 {
() => {
{
i += 2;
if i > data.len() {
return Err(format!("{}: {}: pop_n16", file!(), line!()));
}
u16::from(n16::from_bytes(&data[i - 2 .. i]))
}
};
};
macro_rules! pop_data {
() => {
{
let mut data = Vec::new();
let data_len = pop_n16!();
for _data_i in 0..data_len {
data.push(pop_u8!());
}
data
}
};
};
macro_rules! pop_name {
() => {
{
let mut name = String::new();
let old_i = i;
loop {
let name_len = pop_u8!();
if name_len & name_ind == name_ind {
i -= 1;
i = (pop_n16!() - ((name_ind as u16) << 8)) as usize;
continue;
}
if name_len == 0 {
break;
}
if ! name.is_empty() {
name.push('.');
}
for _name_i in 0..name_len {
name.push(pop_u8!() as char);
}
}
if i <= old_i {
i = old_i + 2;
}
name
}
};
};
let transaction_id = pop_n16!();
let flags = pop_n16!();
let queries_len = pop_n16!();
let answers_len = pop_n16!();
pop_n16!();
pop_n16!();
let mut queries = Vec::new();
for _query_i in 0..queries_len {
queries.push(DnsQuery {
name: pop_name!(),
q_type: pop_n16!(),
q_class: pop_n16!()
});
}
let mut answers = Vec::new();
for _answer_i in 0..answers_len {
answers.push(DnsAnswer {
name: pop_name!(),
a_type: pop_n16!(),
a_class: pop_n16!(),
ttl_a: pop_n16!(),
ttl_b: pop_n16!(),
data: pop_data!()
});
}
Ok(Dns {
transaction_id: transaction_id,
flags: flags,
queries: queries,
answers: answers,
})
}
}
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use alloc::String;
#[derive(Clone, Debug)]
pub struct DnsQuery {
pub name: String,
pub q_type: u16,
pub q_class: u16
}
use alloc::string::String;
use platform::rawfile::RawFile;
use platform::Line;
use platform::rlb::RawLineBuffer;
use c_str::CString;
pub fn get_dns_server() -> String {
let fd = match RawFile::open(&CString::new("/etc/resolv.conf").unwrap(), 0, 0) {
Ok(fd) => fd,
Err(_) => return String::new() // TODO: better error handling
};
let mut rlb = RawLineBuffer::new(*fd);
while let Line::Some(line) = rlb.next() {
if line.starts_with(b"nameserver ") {
return String::from_utf8(line[11..].to_vec()).unwrap_or_default();
}
}
// TODO: better error handling
String::new()
}
This diff is collapsed.
use alloc::string::String;
use c_str::CString;
use platform::rawfile::file_read_all;
pub fn get_dns_server() -> String {
String::from_utf8(file_read_all(&CString::new("/etc/net/dns").unwrap()).unwrap()).unwrap()
}
......@@ -7,7 +7,7 @@ pub type in_addr_t = u32;
pub type in_port_t = u16;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Default)]
pub struct in_addr {
pub s_addr: in_addr_t,
}
......@@ -18,10 +18,12 @@ pub struct in6_addr {
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: in_port_t,
pub sin_addr: in_addr,
pub _pad: [c_char; 8],
}
#[repr(C)]
......
......@@ -7,7 +7,7 @@ use c_str::CStr;
use header::{errno, fcntl};
use platform;
use platform::types::*;
use platform::RawFile;
use platform::{Line, RawFile, RawLineBuffer};
use platform::{Pal, Sys};
#[repr(C)]
......@@ -56,54 +56,16 @@ where
Err(_) => return OptionPasswd::Error,
};
let mut buf = Vec::new();
let mut newline = None;
let mut rlb = RawLineBuffer::new(*file);
loop {
// TODO when nll becomes a thing:
// let mut newline;
// WORKAROUND:
if let Some(newline) = newline {
buf.drain(..newline + 1);
}
// Read until newline
loop {
newline = buf.iter().position(|b| *b == b'\n');
if newline.is_some() {
break;
}
let len = buf.len();
if len >= buf.capacity() {
buf.reserve(1024);
}
unsafe {
let capacity = buf.capacity();
buf.set_len(capacity);
}
let read = Sys::read(*file, &mut buf[len..]);
unsafe {
buf.set_len(len + read as usize);
}
if read == 0 {
return OptionPasswd::NotFound;
}
if read < 0 {
return OptionPasswd::Error;
}
}
let line = match rlb.next() {
Line::Error => return OptionPasswd::Error,
Line::EOF => return OptionPasswd::NotFound,
Line::Some(line) => line
};
// Parse into passwd
let newline = newline.unwrap(); // safe because it doesn't break the loop otherwise
let line = &buf[..newline];
let mut parts: [&[u8]; 7] = [&[]; 7];
for (i, part) in line.splitn(7, |b| *b == b':').enumerate() {
parts[i] = part;
......
use core::fmt::Write as CoreWrite;
use core::{slice, str};
use core::{slice, str, ptr};
use platform::types::*;
use platform::{self, Write};
......@@ -61,8 +61,11 @@ pub unsafe fn printf<W: Write>(w: W, format: *const c_char, mut ap: VaList) -> c
let a = ap.get::<*const c_char>();
found_percent = false;
w.write_str(str::from_utf8_unchecked(platform::c_str(a)))
if a != ptr::null() {
w.write_str(str::from_utf8_unchecked(platform::c_str(a)))
} else {
w.write_str("NULL")
}
}
'u' => {
let a = ap.get::<c_uint>();
......
......@@ -109,6 +109,7 @@ pub unsafe extern "C" fn strcasecmp(mut first: *const c_char, mut second: *const
}
0
}
#[no_mangle]
pub unsafe extern "C" fn strncasecmp(
mut first: *const c_char,
......
sys_includes = ["stddef.h", "stdint.h", "sys/types.h"]
include_guard = "_SYS_SOCKET_H"
style = "Tag"
style = "Both"
language = "C"
[defines]
......
......@@ -14,6 +14,7 @@ pub type sa_family_t = u16;
pub type socklen_t = u32;
#[repr(C)]
#[derive(Default)]
pub struct sockaddr {
pub sa_family: sa_family_t,
data: [c_char; 14],
......
......@@ -44,7 +44,7 @@ pub(crate) const MON_NAMES: [&str; 12] = [
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
];
pub(crate) const CLOCK_REALTIME: clockid_t = 0;
pub const CLOCK_REALTIME: clockid_t = 0;
pub const CLOCK_MONOTONIC: clockid_t = 1;
pub(crate) const CLOCK_PROCESS_CPUTIME_ID: clockid_t = 2;
......
......@@ -29,6 +29,9 @@ pub use self::rawfile::RawFile;
pub mod rawfile;
pub use self::rlb::{Line, RawLineBuffer};
pub mod rlb;
use self::types::*;
pub mod types;
......
use alloc::Vec;
use core::ops::Deref;
use super::{types::*, Pal, Sys};
......@@ -46,3 +47,34 @@ impl Deref for RawFile {
&self.0
}
}
pub fn file_read_all(path: &CStr) -> Result<Vec<u8>, ()> {
let file = RawFile::open(path, 0, 0o644)?;
let mut buf = Vec::new();
let mut len = 0;
loop {
if len >= buf.capacity() {
buf.reserve(32);
unsafe {
let capacity = buf.capacity();
buf.set_len(capacity);
}
}
let read = Sys::read(*file, &mut buf[len..]);
len += read as usize;
if read == 0 {
unsafe { buf.set_len(len); }
return Ok(buf);
}
if read < 0 {
unsafe { buf.set_len(len); }
return Err(());
}
}
}
use alloc::vec::Vec;
use platform::{Pal, Sys};
use platform::types::*;
use header::unistd::{lseek, SEEK_SET};
/// Implements an `Iterator` which returns on either newline or EOF.
#[derive(Clone)]
pub struct RawLineBuffer {
pub fd: c_int,
buf: Vec<u8>,
newline: Option<usize>,
read: usize
}
#[derive(PartialEq)]
pub enum Line<'a> {
Error,
EOF,
Some(&'a [u8])
}
impl RawLineBuffer {
pub const fn new(fd: c_int) -> Self {
Self {
fd: fd,
buf: Vec::new(),
newline: None,
read: 0
}
}
// Can't use iterators because we want to return a reference.
// See https://stackoverflow.com/a/30422716/5069285
pub fn next(&mut self) -> Line {
// Remove last line
if let Some(newline) = self.newline {
self.buf.drain(..newline + 1);
}
loop {
// Exit if newline was read already
self.newline = self.buf.iter().position(|b| *b == b'\n');
if self.newline.is_some() {
break;
}
let len = self.buf.len();
if len >= self.buf.capacity() {
self.buf.reserve(1024);
}
// Create buffer of what's left in the vector, uninitialized memory
unsafe {
let capacity = self.buf.capacity();
self.buf.set_len(capacity);
}
let read = Sys::read(self.fd, &mut self.buf[len..]);
let read_usize = read.max(0) as usize;
// Remove all uninitialized memory that wasn't read
unsafe {
self.buf.set_len(len + read_usize);
}
self.read += read_usize;
if read == 0 {
return Line::EOF;
}
if read < 0 {
return Line::Error;
}
}
let newline = self.newline.unwrap(); // safe because it doesn't break the loop otherwise
Line::Some(&self.buf[..newline])
}
/// Return the byte position of the start of the line
pub fn line_pos(&self) -> usize {
self.read - self.buf.len()
}
/// Seek to a byte position in the file
pub fn seek(&mut self, pos: usize) -> off_t {
let ret = lseek(self.fd, pos as i64, SEEK_SET);
if ret != !0 {
self.read = pos;
}
ret
}
}
......@@ -107,6 +107,7 @@ impl<'a> From<&'a timespec> for redox_timespec {
}
#[repr(C)]
#[derive(Default)]
pub struct stat {
pub st_dev: dev_t,
pub st_ino: ino_t,
......
......@@ -10,17 +10,18 @@ EXPECT_BINS=\
fnmatch \
locale \
math \
netdb \
select \
setjmp \
signal \