netatalk 4.5.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
dsi.h File Reference

DSI (Data Stream Interface) protocol definitions. More...

`#include <sys/types.h>`
`#include <arpa/inet.h>`
`#include <netinet/in.h>`
`#include <signal.h>`
`#include <sys/socket.h>`
`#include <sys/time.h>`
`#include <atalk/afp.h>`
`#include <atalk/globals.h>`
`#include <atalk/server_child.h>`

Go to the source code of this file.

## Data Structures
struct | dsi_block
struct | DSI

## Macros
#define | DSI_BLOCKSIZ 16
#define | DSI_DATASIZ 65536
#define | DSIFL_REQUEST 0x00
#define | DSIFL_REPLY 0x01
#define | DSIFL_MAX 0x01
#define | DSIOPT_SERVQUANT 0x00
#define | DSIOPT_ATTNQUANT 0x01
#define | DSIOPT_REPLCSIZE 0x02
#define | DSIFUNC_CLOSE 1
#define | DSIFUNC_CMD 2
#define | DSIFUNC_STAT 3
#define | DSIFUNC_OPEN 4
#define | DSIFUNC_TICKLE 5
#define | DSIFUNC_WRITE 6
#define | DSIFUNC_ATTN 8
#define | DSIFUNC_MAX 8
#define | DSIERR_OK 0x0000
#define | DSIERR_BADVERS 0xfbd6
#define | DSIERR_BUFSMALL 0xfbd5
#define | DSIERR_NOSESS 0xfbd4
#define | DSIERR_NOSERV 0xfbd3
#define | DSIERR_PARM 0xfbd2
#define | DSIERR_SERVBUSY 0xfbd1
#define | DSIERR_SESSCLOS 0xfbd0
#define | DSIERR_SIZERR 0xfbcf
#define | DSIERR_TOOMANY 0xfbce
#define | DSIERR_NOACK 0xfbcd
#define | DSI_DEFQUANT 2
#define | DSI_SERVQUANT_MAX 0xffffffff
#define | DSI_SERVQUANT_MIN 32000
#define | DSI_SERVQUANT_DEF 0x100000L
#define | DSI_AFPOVERTCP_PORT 548
#define | DSI_DATA (1 << 0)
#define | DSI_RUNNING (1 << 1)
#define | DSI_SLEEPING (1 << 2)
#define | DSI_EXTSLEEP (1 << 3)
#define | DSI_DISCONNECTED (1 << 4)
#define | DSI_DIE (1 << 5)
#define | DSI_NOREPLY (1 << 6)
#define | DSI_RECONSOCKET (1 << 7)
#define | DSI_RECONINPROG (1 << 8)
#define | DSI_AFP_LOGGED_OUT (1 << 9)
#define | DSI_NOWAIT 1
#define | DSI_MSG_MORE 2
#define | dsi_wrtreply(a, b)
#define | dsi_serverID(x)
#define | dsi_send(x)

## Typedefs
typedef struct DSI | DSI

## Functions
DSI * | dsi_init (AFPObj *obj, const char *hostname, const char *address, const char *port)
void | dsi_setstatus (DSI *, char *, const size_t)
int | dsi_tcp_init (DSI *dsi, const char *hostname, const char *address, const char *port)
| Initialize DSI over TCP.
void | dsi_free (DSI *dsi)
int | dsi_getsession (DSI *, server_child_t *, const int, afp_child_t **)
| Start a DSI session, fork an afpd process.
void | dsi_kill (int)
void | dsi_opensession (DSI *)
int | dsi_attention (DSI *, AFPUserBytes)
| send an attention.
int | dsi_cmdreply (DSI *, const int)
int | dsi_tickle (DSI *)
void | dsi_getstatus (DSI *)
void | dsi_close (DSI *)
ssize_t | dsi_stream_write (DSI *, void *, const size_t, const int mode)
| write raw DSI data
size_t | dsi_stream_read (DSI *, void *, const size_t)
| Read data from DSI buffer.
int | dsi_stream_send (DSI *, void *, size_t)
| write data.
int | dsi_stream_receive (DSI *)
| Read DSI command and data.
int | dsi_disconnect (DSI *dsi)
| Communication error with the client, enter disconnected state.
ssize_t | dsi_stream_read_file (DSI *, int, off_t off, const size_t len, const int err)
size_t | dsi_writeinit (DSI *, void *, const size_t)
size_t | dsi_write (DSI *, void *, const size_t)
void | dsi_writeflush (DSI *)
ssize_t | dsi_readinit (DSI *, void *, const size_t, const size_t, const int)
| streaming i/o for afp_read.
ssize_t | dsi_read (DSI *, void *, const size_t)
void | dsi_readdone (DSI *)

## Detailed Description

DSI (Data Stream Interface) protocol definitions.

What a DSI packet looks like:

0 32
|-------------------------------|
|flags |command| requestID |
|-------------------------------|
|error code/enclosed data offset|
|-------------------------------|
|total data length |
|-------------------------------|
|reserved field |
|-------------------------------|
flags
static dbd_flags_t flags
Definition cmd_dbd.c:43
data
#define data
Definition hash.c:38

Note
  CONVENTION: anything with a dsi_ prefix is kept in network byte order.

## Macro Definition Documentation

## ◆ DSI_AFP_LOGGED_OUT

#define DSI_AFP_LOGGED_OUT (1 << 9)

client called afp_logout, quit on next EOF from socket

## ◆ DSI_AFPOVERTCP_PORT

#define DSI_AFPOVERTCP_PORT 548

default port number

## ◆ DSI_BLOCKSIZ

#define DSI_BLOCKSIZ 16

## ◆ DSI_DATA

#define DSI_DATA (1 << 0)

we have received a DSI command

## ◆ DSI_DATASIZ

#define DSI_DATASIZ 65536

## ◆ DSI_DEFQUANT

#define DSI_DEFQUANT 2

default attention quantum size

## ◆ DSI_DIE

#define DSI_DIE (1 << 5)

SIGUSR1, going down in 5 minutes

## ◆ DSI_DISCONNECTED

#define DSI_DISCONNECTED (1 << 4)

we're in diconnected state after a socket error

## ◆ DSI_EXTSLEEP

#define DSI_EXTSLEEP (1 << 3)

we're sleeping after FPZzz

## ◆ DSI_MSG_MORE

#define DSI_MSG_MORE 2

## ◆ DSI_NOREPLY

#define DSI_NOREPLY (1 << 6)

in dsi_write we generate our own replies

## ◆ DSI_NOWAIT

#define DSI_NOWAIT 1

## ◆ DSI_RECONINPROG

#define DSI_RECONINPROG (1 << 8)

used in the new session in reconnect

## ◆ DSI_RECONSOCKET

#define DSI_RECONSOCKET (1 << 7)

we have a new socket from primary reconnect

## ◆ DSI_RUNNING

#define DSI_RUNNING (1 << 1)

we have received a AFP command

## ◆ dsi_send

#define dsi_send | ( |  | x | ) |

Value:
do { \
(x)->header.dsi_len = htonl((x)->cmdlen); \
dsi_stream_send((x), (x)->commands, (x)->cmdlen); \
} while (0)
header
static void header(void)
Print test header with timestamp.
Definition speedtest.c:742

## ◆ dsi_serverID

#define dsi_serverID | ( |  | x | ) |

Value:
((x)->serverID++)

## ◆ DSI_SERVQUANT_DEF

#define DSI_SERVQUANT_DEF 0x100000L

default server quantum (1 MB)

## ◆ DSI_SERVQUANT_MAX

#define DSI_SERVQUANT_MAX 0xffffffff

server quantum

## ◆ DSI_SERVQUANT_MIN

#define DSI_SERVQUANT_MIN 32000

minimum server quantum

## ◆ DSI_SLEEPING

#define DSI_SLEEPING (1 << 2)

we're sleeping after FPZzz

## ◆ dsi_wrtreply

#define dsi_wrtreply | ( |  | a,
|  |  | b )

Value:
dsi_cmdreply(a,b)
dsi_cmdreply
int dsi_cmdreply(DSI *, const int)
Definition dsi_cmdreply.c:19

## ◆ DSIERR_BADVERS

#define DSIERR_BADVERS 0xfbd6

## ◆ DSIERR_BUFSMALL

#define DSIERR_BUFSMALL 0xfbd5

## ◆ DSIERR_NOACK

#define DSIERR_NOACK 0xfbcd

## ◆ DSIERR_NOSERV

#define DSIERR_NOSERV 0xfbd3

## ◆ DSIERR_NOSESS

#define DSIERR_NOSESS 0xfbd4

## ◆ DSIERR_OK

#define DSIERR_OK 0x0000

## ◆ DSIERR_PARM

#define DSIERR_PARM 0xfbd2

## ◆ DSIERR_SERVBUSY

#define DSIERR_SERVBUSY 0xfbd1

## ◆ DSIERR_SESSCLOS

#define DSIERR_SESSCLOS 0xfbd0

## ◆ DSIERR_SIZERR

#define DSIERR_SIZERR 0xfbcf

## ◆ DSIERR_TOOMANY

#define DSIERR_TOOMANY 0xfbce

## ◆ DSIFL_MAX

#define DSIFL_MAX 0x01

## ◆ DSIFL_REPLY

#define DSIFL_REPLY 0x01

## ◆ DSIFL_REQUEST

#define DSIFL_REQUEST 0x00

## ◆ DSIFUNC_ATTN

#define DSIFUNC_ATTN 8

DSIAttention

## ◆ DSIFUNC_CLOSE

#define DSIFUNC_CLOSE 1

DSICloseSession

## ◆ DSIFUNC_CMD

#define DSIFUNC_CMD 2

DSICommand

## ◆ DSIFUNC_MAX

#define DSIFUNC_MAX 8

largest command

## ◆ DSIFUNC_OPEN

#define DSIFUNC_OPEN 4

DSIOpenSession

## ◆ DSIFUNC_STAT

#define DSIFUNC_STAT 3

DSIGetStatus

## ◆ DSIFUNC_TICKLE

#define DSIFUNC_TICKLE 5

DSITickle

## ◆ DSIFUNC_WRITE

#define DSIFUNC_WRITE 6

DSIWrite

## ◆ DSIOPT_ATTNQUANT

#define DSIOPT_ATTNQUANT 0x01

attention quantum

## ◆ DSIOPT_REPLCSIZE

#define DSIOPT_REPLCSIZE 0x02

AFP replaycache size supported by the server (that's us)

## ◆ DSIOPT_SERVQUANT

#define DSIOPT_SERVQUANT 0x00

server request quantum

## Typedef Documentation

## ◆ DSI

typedef struct DSI DSI

## Function Documentation

## ◆ dsi_attention()

int dsi_attention | ( | DSI * | dsi,
|  | AFPUserBytes | flags )
| extern

send an attention.

Note
  this may get called at any time, so we can't use DSI buffers to send one.

Returns
  0 on error

## ◆ dsi_close()

void dsi_close | ( | DSI * | dsi | ) |
| extern

## ◆ dsi_cmdreply()

int dsi_cmdreply | ( | DSI * | dsi,
|  | const int | err )
| extern

## ◆ dsi_disconnect()

int dsi_disconnect | ( | DSI * | dsi | ) |
| extern

Communication error with the client, enter disconnected state.

1. close the socket
2. set the DSI_DISCONNECTED flag, remove possible sleep flags

Returns
  0 if successfully entered disconnected state
  -1 if ppid is 1 which means afpd master died, or euid == 0 i.e. where still running as root (unauthenticated session)

## ◆ dsi_free()

void dsi_free | ( | DSI * | dsi | ) |
| extern

Free any allocated resources of the master afpd DSI objects and close server socket

## ◆ dsi_getsession()

int dsi_getsession | ( | DSI * | dsi,
|  | server_child_t * | serv_children,
|  | int | tickleval,
|  | afp_child_t ** | childp )
| extern

Start a DSI session, fork an afpd process.

Parameters

  [in,out] | dsi | DSI structure
  [in,out] | serv_children | pointer to our structure with all childs
  [in] | tickleval | tickle interval in seconds
  [out] | childp | after fork: parent return pointer to child, child returns NULL

Returns
  0 on success, any other value denotes failure

## ◆ dsi_getstatus()

void dsi_getstatus | ( | DSI * | dsi | ) |
| extern

## ◆ dsi_init()

DSI * dsi_init | ( | AFPObj * | obj,
|  | const char * | hostname,
|  | const char * | address,
|  | const char * | port )
| extern

## ◆ dsi_kill()

void dsi_kill | ( | int |  | ) |
| extern

## ◆ dsi_opensession()

void dsi_opensession | ( | DSI * | dsi | ) |
| extern

OpenSession. set up the connection

## ◆ dsi_read()

ssize_t dsi_read | ( | DSI * | dsi,
|  | void * | buf,
|  | const size_t | buflen )
| extern

send off the data

## ◆ dsi_readdone()

void dsi_readdone | ( | DSI * | dsi | ) |
| extern

## ◆ dsi_readinit()

ssize_t dsi_readinit | ( | DSI * | dsi,
|  | void * | buf,
|  | const size_t | buflen,
|  | const size_t | size,
|  | const int | err )
| extern

streaming i/o for afp_read.

this is all from the perspective of the client. it basically does the reverse of dsi_write. on first entry, it will send off the header plus whatever is in its command buffer. it returns the amount of stuff still to be read (constrained by the buffer size).

## ◆ dsi_setstatus()

void dsi_setstatus | ( | DSI * | ,
|  | char * | ,
|  | const size_t | )
| extern

## ◆ dsi_stream_read()

size_t dsi_stream_read | ( | DSI * | dsi,
|  | void * | data,
|  | const size_t | length )
| extern

Read data from DSI buffer.

Essentially a loop around buf_read() to ensure "length" bytes are read from dsi->buffer and/or the socket.

Returns
  length on success, some value smaller than length indicates an error

## ◆ dsi_stream_read_file()

ssize_t dsi_stream_read_file | ( | DSI * | dsi,
|  | int | fromfd,
|  | off_t | off,
|  | const size_t | len,
|  | const int | err )
| extern

## ◆ dsi_stream_receive()

int dsi_stream_receive | ( | DSI * | dsi | ) |
| extern

Read DSI command and data.

Parameters

  dsi | (rw) DSI handle

Returns
  DSI function on success, 0 on failure

## ◆ dsi_stream_send()

int dsi_stream_send | ( | DSI * | dsi,
|  | void * | buf,
|  | size_t | length )
| extern

write data.

Returns
  0 on failure.

Note
  this assumes that dsi_len will never cause an overflow in the data buffer.

## ◆ dsi_stream_write()

ssize_t dsi_stream_write | ( | DSI * | dsi,
|  | void * | data,
|  | const size_t | length,
|  | int | mode )
| extern

write raw DSI data

Checks against EINTR aren't necessary if all of the signals have SA_RESTART specified.

Returns
  actual bytes written, -1 on error

## ◆ dsi_tcp_init()

int dsi_tcp_init | ( | DSI * | dsi,
|  | const char * | hostname,
|  | const char * | inaddress,
|  | const char * | inport )
| extern

Initialize DSI over TCP.

Parameters

  [in,out] | dsi | DSI handle
  [in] | hostname | pointer to hostname string
  [in] | inaddress | Optional IPv4 or IPv6 address with an optional port, may be NULL
  [in] | inport | pointer to port string

Creates listening AFP/DSI socket. If the parameter inaddress is NULL, then we listen on the wildcard address, i,e, on all interfaces. That should mean listening on the IPv6 address "::" on IPv4/IPv6 dual stack kernels, accepting both v4 and v6 requests.

If the parameter inaddress is not NULL, then we only listen on the given address. The parameter may contain a port number using the URL format for address and port:

IPv4, IPv4:port, IPv6, [IPv6], [IPv6]:port

Parameter inport must be a valid pointer to a port string and is used if the inaddress parameter doesn't contain a port.

Returns
  0 on success, -1 on failure

## ◆ dsi_tickle()

int dsi_tickle | ( | DSI * | dsi | ) |
| extern

server generated tickles. as this is only called by the tickle handler, we don't need to block signals.

## ◆ dsi_write()

size_t dsi_write | ( | DSI * | dsi,
|  | void * | buf,
|  | const size_t | buflen )
| extern

fill up buf and then return. this should be called repeatedly until all the data has been read. i block alarm processing during the transfer to avoid sending unnecessary tickles.

## ◆ dsi_writeflush()

void dsi_writeflush | ( | DSI * | dsi | ) |
| extern

flush any unread buffers.

## ◆ dsi_writeinit()

size_t dsi_writeinit | ( | DSI * | dsi,
|  | void * | buf,
|  | const size_t | buflen )
| extern