1/*
2 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
3 * All rights reserved. See COPYRIGHT.
4 */
5
6#ifdef HAVE_CONFIG_H
7#include "config.h"
8#endif /* HAVE_CONFIG_H */
9
10#include <stdio.h>
11#include <string.h>
12#include <sys/types.h>
13#include <stdlib.h>
14
15#include <atalk/dsi.h>
16#include <atalk/util.h>
17#include <atalk/logger.h>
18
19static void dsi_init_buffer(DSI *dsi)
20{
21    size_t quantum = dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF;
22
23    /* default is 12 * 300k = 3,6 MB (Apr 2011) */
24    if ((dsi->buffer = malloc(dsi->dsireadbuf * quantum)) == NULL) {
25        LOG(log_error, logtype_dsi, "dsi_init_buffer: OOM");
26        AFP_PANIC("OOM in dsi_init_buffer");
27    }
28    dsi->start = dsi->buffer;
29    dsi->eof = dsi->buffer;
30    dsi->end = dsi->buffer + (dsi->dsireadbuf * quantum);
31}
32
33/* OpenSession. set up the connection */
34void dsi_opensession(DSI *dsi)
35{
36  u_int32_t i = 0; /* this serves double duty. it must be 4-bytes long */
37  int offs;
38
39  dsi_init_buffer(dsi);
40  if (setnonblock(dsi->socket, 1) < 0) {
41      LOG(log_error, logtype_dsi, "dsi_opensession: setnonblock: %s", strerror(errno));
42      AFP_PANIC("setnonblock error");
43  }
44
45  /* parse options */
46  while (i < dsi->cmdlen) {
47    switch (dsi->commands[i++]) {
48    case DSIOPT_ATTNQUANT:
49      memcpy(&dsi->attn_quantum, dsi->commands + i + 1, dsi->commands[i]);
50      dsi->attn_quantum = ntohl(dsi->attn_quantum);
51
52    case DSIOPT_SERVQUANT: /* just ignore these */
53    default:
54      i += dsi->commands[i] + 1; /* forward past length tag + length */
55      break;
56    }
57  }
58
59  /* let the client know the server quantum. we don't use the
60   * max server quantum due to a bug in appleshare client 3.8.6. */
61  dsi->header.dsi_flags = DSIFL_REPLY;
62  dsi->header.dsi_code = 0;
63  /* dsi->header.dsi_command = DSIFUNC_OPEN;*/
64
65  dsi->cmdlen = 2 * (2 + sizeof(i)); /* length of data. dsi_send uses it. */
66
67  /* DSI Option Server Request Quantum */
68  dsi->commands[0] = DSIOPT_SERVQUANT;
69  dsi->commands[1] = sizeof(i);
70  i = htonl(( dsi->server_quantum < DSI_SERVQUANT_MIN ||
71	      dsi->server_quantum > DSI_SERVQUANT_MAX ) ?
72	    DSI_SERVQUANT_DEF : dsi->server_quantum);
73  memcpy(dsi->commands + 2, &i, sizeof(i));
74
75  /* AFP replaycache size option */
76  offs = 2 + sizeof(i);
77  dsi->commands[offs] = DSIOPT_REPLCSIZE;
78  dsi->commands[offs+1] = sizeof(i);
79  i = htonl(REPLAYCACHE_SIZE);
80  memcpy(dsi->commands + offs + 2, &i, sizeof(i));
81  dsi_send(dsi);
82}
83